diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml index ca43515e8f..e3e556f942 100644 --- a/.github/workflows/backend.yml +++ b/.github/workflows/backend.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 + - name: build-test + run: cd twake && docker-compose -f docker-compose.tests.yml run -e NODE_OPTIONS=--unhandled-rejections=warn node npm run build - name: unit-test run: cd twake && docker-compose -f docker-compose.tests.yml run -e NODE_OPTIONS=--unhandled-rejections=warn node npm run test:unit - name: e2e-mongo-test diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml new file mode 100644 index 0000000000..8412872ea6 --- /dev/null +++ b/.github/workflows/integration-test.yml @@ -0,0 +1,23 @@ +name: integration-test + +on: + pull_request: + branches: [main, develop, qa, canary] + paths: + - "twake/**" + +jobs: + test: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: build + run: cd twake && docker build -t integration-test -f docker/integration-test/Dockerfile . + - name: build-node + run: cd twake && docker build -t twaketech/twake-node -f docker/twake-node/Dockerfile . + - name: run-twake-instance + run: cd twake && docker-compose -f docker-compose.onpremise.mongo.yml up -d && sleep 60 + - name: get-logs + run: cd twake && docker-compose -f docker-compose.onpremise.mongo.yml logs && curl http://localhost:3000 + - name: run integration-test + run: cd twake && docker run --network host -e SERVER=http://localhost:3000 integration-test diff --git a/.github/workflows/saas-update-backend.yml b/.github/workflows/saas-update-backend.yml index f943b10469..70f5d87ee7 100644 --- a/.github/workflows/saas-update-backend.yml +++ b/.github/workflows/saas-update-backend.yml @@ -13,13 +13,13 @@ jobs: deploy-php: runs-on: ubuntu-20.04 steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') - run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/qa') - run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/canary') run: 'echo "DOCKERTAG=canary" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-canary" >> $GITHUB_ENV' @@ -40,13 +40,13 @@ jobs: deploy-node: runs-on: ubuntu-20.04 steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') - run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/qa') - run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/canary') run: 'echo "DOCKERTAG=canary" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-canary" >> $GITHUB_ENV' @@ -62,5 +62,6 @@ jobs: password: ${{ secrets.DOCKER_PASSWORD }} workdir: twake context: . + target: production buildoptions: "-t twaketech/twake-node -f docker/twake-node/Dockerfile" tags: "${{ env.DOCKERTAG }},${{ env.DOCKERTAGVERSION }}" diff --git a/.github/workflows/saas-update-front.yml b/.github/workflows/saas-update-front.yml index bd287bb520..3f35f8db42 100644 --- a/.github/workflows/saas-update-front.yml +++ b/.github/workflows/saas-update-front.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: - node-version: [12.x] + node-version: [14.x] steps: - uses: actions/checkout@v2 @@ -48,13 +48,13 @@ jobs: runs-on: ubuntu-20.04 if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/qa' || github.ref == 'refs/heads/canary' steps: - - run: 'echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + - run: 'echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/develop') - run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=develop" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/qa') - run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2021.Q4.846" >> $GITHUB_ENV' + run: 'echo "DOCKERTAG=qa" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=2022.Q4.1120" >> $GITHUB_ENV' - name: Set env to develop if: endsWith(github.ref, '/canary') run: 'echo "DOCKERTAG=canary" >> $GITHUB_ENV; echo "DOCKERTAGVERSION=${{ env.DOCKERTAGVERSION }}-canary" >> $GITHUB_ENV' diff --git a/.gitignore b/.gitignore index 75483c4b9b..eb1b35348e 100644 --- a/.gitignore +++ b/.gitignore @@ -143,4 +143,5 @@ userreport.sh private -log-workforce.sh \ No newline at end of file +log-workforce.sh +.dccache diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32790e3e3b..2c863d8526 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,10 @@ # Contributing to Twake -Hey! Thank you for your interest in contributing to Twake, we really appreciate it. +Hey! Thank you for your interest in contributing to Twake, we really appreciate it. -Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. - -We are an open-source project and we love to receive contributions from our community! There are many ways to contribute - writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests, fixing bugs, submitting pull requests for enhancements, or reviewing other's pull requests. +Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. +We are an open-source project and we love to receive contributions from our community! There are many ways to contribute - writing tutorials or blog posts, improving the documentation, submitting bug reports and feature requests, fixing bugs, submitting pull requests for enhancements, or reviewing other's pull requests. ## In a nutshell @@ -13,45 +12,40 @@ We are an open-source project and we love to receive contributions from our comm - Fork this repository to start working and create a new working branch on top of the develop branch preferably. - To propose your changes, open a PR from your fork and target the **develop** branch. +Get more information here about how to start writing code: https://doc.twake.app/gettingstarted/installation/run-twake-as-developer ## Ground Rules -Please adhere to the following responsibilities: +Please adhere to the following responsibilities: -- Ensure cross-platform compatibility for every change that's accepted. For example, Windows, Mac, Debian & Ubuntu Linux. -- Any change must be done using **Pull Requests** incoming from a fork of original Twake repository. -- Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback. -- Don't add any classes to the codebase unless absolutely needed. Err on the side of using functions. -- Keep feature versions as small as possible, preferably one new feature per version. +- Ensure cross-platform compatibility for every change that's accepted. For example, Windows, Mac, Debian & Ubuntu Linux. +- Any change must be done using **Pull Requests** incoming from a fork of original Twake repository. +- Create issues for any major changes and enhancements that you wish to make. Discuss things transparently and get community feedback. +- Don't add any classes to the codebase unless absolutely needed. Err on the side of using functions. +- Keep feature versions as small as possible, preferably one new feature per version. - Be welcoming to newcomers and encourage diverse new contributions from all backgrounds. See the [Code of Conduct](https://github.com/linagora/Twake/blob/main/CODE_OF_CONDUCT.md) - - #### What does the Code of Conduct mean for You? -Our [Code of Conduct](https://github.com/linagora/Twake/blob/main/CODE_OF_CONDUCT.md) means that you are responsible for treating everyone on the project with respect and courtesy regardless of their identity. If you are the victim of any inappropriate behavior or comments as described in our [Code of Conduct](https://github.com/linagora/Twake/blob/main/CODE_OF_CONDUCT.md), we are here for you. Please follow the guidelines on our [website](https://linagora.com/en/) to report the issue and we will do the best to ensure that the abuser is reprimanded appropriately per our code. - - +Our [Code of Conduct](https://github.com/linagora/Twake/blob/main/CODE_OF_CONDUCT.md) means that you are responsible for treating everyone on the project with respect and courtesy regardless of their identity. If you are the victim of any inappropriate behavior or comments as described in our [Code of Conduct](https://github.com/linagora/Twake/blob/main/CODE_OF_CONDUCT.md), we are here for you. Please follow the guidelines on our [website](https://linagora.com/en/) to report the issue and we will do the best to ensure that the abuser is reprimanded appropriately per our code. ## Your First Contribution? -Unsure where to begin contributing to Twake? You can start by looking at these [good first issues](https://github.com/linagora/Twake/labels/good%20first%20issue) and [help wanted issues](https://github.com/linagora/Twake/labels/help%20wanted). Good first issues - issues which should require only a few lines of code, and a test or two. Help wanted issues - issues which should be a bit more involved than beginner issues. While not perfect, number of comments is a reasonable proxy for impact a given change will have. +Unsure where to begin contributing to Twake? You can start by looking at these [good first issues](https://github.com/linagora/Twake/labels/good%20first%20issue) and [help wanted issues](https://github.com/linagora/Twake/labels/help%20wanted). Good first issues - issues which should require only a few lines of code, and a test or two. Help wanted issues - issues which should be a bit more involved than beginner issues. While not perfect, number of comments is a reasonable proxy for impact a given change will have. -Working on your first Pull Request? You can learn how from these free resources: [Course - How to Contribute to an Open Source Project on GitHub from @kentcdodds on @eggheadio](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github) and [Make a Pull Request](https://makeapullrequest.com/). +Working on your first Pull Request? You can learn how from these free resources: [Course - How to Contribute to an Open Source Project on GitHub from @kentcdodds on @eggheadio](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github) and [Make a Pull Request](https://makeapullrequest.com/). At this point, you are ready to make your changes! Feel free to ask for help; everyone is a beginner at first. 😃 -If a maintainer asks you to "rebase" your PR, they are saying that a lot of code has changed, and that you need to update your branch so it's easier to merge. - - +If a maintainer asks you to "rebase" your PR, they are saying that a lot of code has changed, and that you need to update your branch so it's easier to merge. ## How to Contribute? -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. +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. #### Pull Requests -**It's important to break your feature down into small pieces first,** each piece should become it's own pull request. Once you know, what the first small piece of your feature will be, follow this general process while working: +**It's important to break your feature down into small pieces first,** each piece should become it's own pull request. Once you know, what the first small piece of your feature will be, follow this general process while working: 1. Create your own fork of the code and do changes in your own fork. @@ -59,85 +53,73 @@ When contributing to this repository, please first discuss the change you wish t - Make sure that the titles of your pull requests and commits respect this format - [Commit & Pull Request Format](https://github.com/linagora/Twake/blob/main/Contribute/Commit%20%26%20Pull%20Request%20Title%20Format.md) - - Write a detailed description of the problem you are solving, the part of Twake it affects, and how you plan on fixing it. + - Write a detailed description of the problem you are solving, the part of Twake it affects, and how you plan on fixing it. - If you have write access, add the **[Status] In Progress** label or wait until somebody adds it. This indicates that the pull request is not ready for a review and may still be incomplete. On the other hand, it welcomes early feedback and encourages collaboration during the development process. -3. Start developing and pushing out commits to your new branch. +3. Start developing and pushing out commits to your new branch. - - Push your changes out frequently and try to avoid getting stuck in a long-running branch or a merge nightmare. Smaller changes are much easier to review and to deal with potential conflicts. - - Note that you can automate some of these tasks by setting up githooks and they will run whenever you `git commit`. - - Please feel free to change, [squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html), and rearrange commits or to force push. Keep in mind, however, that if other people are committing on the same branch then you can mess up their history. You are perfectly safe if you are the only one pushing commits to that branch. - - Squash minor commits such as typo fixes or fixes to previous commits in the pull request. + - Push your changes out frequently and try to avoid getting stuck in a long-running branch or a merge nightmare. Smaller changes are much easier to review and to deal with potential conflicts. + - Note that you can automate some of these tasks by setting up githooks and they will run whenever you `git commit`. + - Please feel free to change, [squash](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html), and rearrange commits or to force push. Keep in mind, however, that if other people are committing on the same branch then you can mess up their history. You are perfectly safe if you are the only one pushing commits to that branch. + - Squash minor commits such as typo fixes or fixes to previous commits in the pull request. -4. If you end up needing more than a few commits, consider splitting the pull request into separate components. Discuss in the new pull request and in the comments why the branch was broken apart and any changes that may have taken place that necessitated the split. Our goal is to catch early in the review process those pull requests that attempt to do too much. +4. If you end up needing more than a few commits, consider splitting the pull request into separate components. Discuss in the new pull request and in the comments why the branch was broken apart and any changes that may have taken place that necessitated the split. Our goal is to catch early in the review process those pull requests that attempt to do too much. -5. When you feel that you are ready for a formal review or for merging into `trunk` make sure you check this list. +5. When you feel that you are ready for a formal review or for merging into `trunk` make sure you check this list. - Make sure your branch merges cleanly and consider rebasing against `trunk` to keep the branch history short and clean. You must target the **develop** branch for your changes. - - If there are visual changes, add before and after screenshots in the pull request comments. - - Add unit tests, or at a minimum, provide helpful instructions for the reviewer so they can test your changes. This will help speed up the review process. - - Ensure that your commit messages are [meaningful](https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message). - - Mention that the PR is ready for review or if you have write access remove the **[Status] In Progress** label from the pull request and add the **[Status] Needs Review** label - someone will provide feedback on the latest unreviewed changes. The reviewer will also mark the pull request as **[Status] Needs Author Reply** if they think you need to change anything. - -6. If you get a :thumbsup: and the status has been changed to **[Status] Ready to Merge** - this is great - the pull request is ready to be merged. - -If you feel yourself waiting for someone to review a PR, don't hesitate to personally ask for someone to review it or to mention them on Github. Remember, the PR author is responsible for pushing the change through. + - If there are visual changes, add before and after screenshots in the pull request comments. + - Add unit tests, or at a minimum, provide helpful instructions for the reviewer so they can test your changes. This will help speed up the review process. + - Ensure that your commit messages are [meaningful](https://thoughtbot.com/blog/5-useful-tips-for-a-better-commit-message). + - Mention that the PR is ready for review or if you have write access remove the **[Status] In Progress** label from the pull request and add the **[Status] Needs Review** label - someone will provide feedback on the latest unreviewed changes. The reviewer will also mark the pull request as **[Status] Needs Author Reply** if they think you need to change anything. +6. If you get a :thumbsup: and the status has been changed to **[Status] Ready to Merge** - this is great - the pull request is ready to be merged. +If you feel yourself waiting for someone to review a PR, don't hesitate to personally ask for someone to review it or to mention them on Github. Remember, the PR author is responsible for pushing the change through. #### Sign your work -We use the Developer Certificate of Origin (DCO) as an additional safeguard for the Linagora/Twake projects. This is a well established and widely used mechanism to assure contributors have confirmed their right to license their contributions under the project's license. Please read [Developer Certificate of Origin](https://github.com/linagora/Twake/blob/main/Contribute/Linagora%20Developer's%20Certificate%20of%20Origin.md). If you can certify it, then just add a line to every git commit message: +We use the Developer Certificate of Origin (DCO) as an additional safeguard for the Linagora/Twake projects. This is a well established and widely used mechanism to assure contributors have confirmed their right to license their contributions under the project's license. Please read [Developer Certificate of Origin](https://github.com/linagora/Twake/blob/main/Contribute/Linagora%20Developer's%20Certificate%20of%20Origin.md). If you can certify it, then just add a line to every git commit message: `Signed-Off by: Unicorn John ` -Use your real name (sorry, no pseudonyms or anonymous contributions). If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit-s`. - - +Use your real name (sorry, no pseudonyms or anonymous contributions). If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit-s`. #### Code Reviews -Code Reviews are an important part of the Twake workflow. They help to keep code quality consistent, and they help every person working on Twake learn and improve over time. We want to make you the best Twake contributor you can be. +Code Reviews are an important part of the Twake workflow. They help to keep code quality consistent, and they help every person working on Twake learn and improve over time. We want to make you the best Twake contributor you can be. -Every PR should be reviewed and approved by someone other than the author, even if the author has write access. Fresh eyes can find problems that can hide in the open if you have been working on the code for a while. +Every PR should be reviewed and approved by someone other than the author, even if the author has write access. Fresh eyes can find problems that can hide in the open if you have been working on the code for a while. -The recommended way of finding an appropriate person to review your code is by [blaming](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) one of the files you are updating and looking at who was responsible for previous commits on that file. +The recommended way of finding an appropriate person to review your code is by [blaming](https://docs.github.com/en/github/managing-files-in-a-repository/tracking-changes-in-a-file) one of the files you are updating and looking at who was responsible for previous commits on that file. -Then, you may ask that person to review your code by mentioning their Github username on the PR comments like this: +Then, you may ask that person to review your code by mentioning their Github username on the PR comments like this: `cc @username` -*Everyone* is encouraged to review PRs and add feedback and ask questions. Reading other people's code is a great way to learn new techniques, and seeing code outside of your own feature helps you to see patterns across the project. It's also helpful to see the feedback other contributors are getting on their PRs. - - +_Everyone_ is encouraged to review PRs and add feedback and ask questions. Reading other people's code is a great way to learn new techniques, and seeing code outside of your own feature helps you to see patterns across the project. It's also helpful to see the feedback other contributors are getting on their PRs. #### Apply a license -In case you are not sure about how to apply our license correctly, please have a look at [How to Apply Licence](https://github.com/linagora/Twake/blob/main/Contribute/HowtoApplyOurLicense.md). - - +In case you are not sure about how to apply our license correctly, please have a look at [How to Apply Licence](https://github.com/linagora/Twake/blob/main/Contribute/HowtoApplyOurLicense.md). -#### How to report a bug? +#### How to report a bug? -If you find a security vulnerability, do NOT open an issue. Email schauhan@linagora.com instead. +If you find a security vulnerability, do NOT open an issue. Email schauhan@linagora.com instead. -In order to determine whether you are dealing with a security issue, ask yourself these two questions: +In order to determine whether you are dealing with a security issue, ask yourself these two questions: - Can I access something that's not mine, or something I should not have access to? -- Can I disable something for other people? +- Can I disable something for other people? - If the answer to either of those two questions are "yes", then you are probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us at schauhan@linagora.com. + If the answer to either of those two questions are "yes", then you are probably dealing with a security issue. Note that even if you answer "no" to both questions, you may still be dealing with a security issue, so if you're unsure, just email us at schauhan@linagora.com. For reporting any other bug, just file [a Github issue.](https://github.com/linagora/Twake/issues/new/choose) +#### How to suggest a feature or enhancement? - -#### How to suggest a feature or enhancement? - -If you find yourself wishing for a feature that doesn't exist in Twake, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Twake has today have been added because our users saw the need. Open an issues on our issues list on Github which describes the feature you would like to see, why you need it. - - +If you find yourself wishing for a feature that doesn't exist in Twake, you are probably not alone. There are bound to be others out there with similar needs. Many of the features that Twake has today have been added because our users saw the need. Open an issues on our issues list on Github which describes the feature you would like to see, why you need it. ## Community diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..162676cbef --- /dev/null +++ b/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + Preamble + +The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + +The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + +Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + +A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + +The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + +An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + +The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + +0. Definitions. + +"This License" refers to version 3 of the GNU Affero General Public License. + +"Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + +"The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + +To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + +A "covered work" means either the unmodified Program or a work based +on the Program. + +To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + +To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + +1. Source Code. + +The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + +A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + +The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + +The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + +The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + +The Corresponding Source for a work in source code form is that +same work. + +2. Basic Permissions. + +All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. + +No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + +When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + +4. Conveying Verbatim Copies. + +You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. + +You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + +A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + +6. Conveying Non-Source Forms. + +You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + +A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + +"Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + +If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + +The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + +7. Additional Terms. + +"Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + +All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + +8. Termination. + +You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + +However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + +Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + +9. Acceptance Not Required for Having Copies. + +You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. + +Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + +An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + +11. Patents. + +A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + +A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + +In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + +If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + +A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. + +If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + +13. Remote Network Interaction; Use with the GNU General Public License. + +Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + +Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + +14. Revised Versions of this License. + +The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + +Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + +15. Disclaimer of Warranty. + +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. + +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. + +If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + +You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index f3eb83374f..0000000000 --- a/LICENSE.md +++ /dev/null @@ -1,729 +0,0 @@ -# GNU Affero General Public License version 3 -License and Additional Terms for TWAKE software - -TWAKE is a secure, open-source, and enterprise-centric SaaS collaboration -platform, distributed under the GNU Affero GPL v3 License terms, with -Additional Terms pursuant to Section 7 of said license. - -These Additional Terms are not intended to be taken as a change of heart by -LINAGORA over the principles of free software and open source distribution, as -LINAGORA strongly believes in free software and open source distribution. -Free and open source software warrants an easy and reasonable access to software -innovation to large user communities, and LINAGORA is highly committed to supporting -free and open source software whenever possible. - -LINAGORA wishes its paternity over TWAKE software to be acknowledged, -regardless of its present or later use, modification, distribution and/or -evolutions. Accordingly, these terms aim at preserving LINAGORA moral rights -over TWAKE. - -We have taken care of not affecting product copying, improvements or deploying. -It is our conviction that the community will not be affected by these terms, -the ultimate goal of which is to ensure the sustainability of free and open -source software by supporting R&D and improving the visibility of LINAGORA as a -free and open source software publisher, while encouraging others to comply -with our common ideals. - -Pursuant to this license, you are therefore free to use the software and modify -it according to the GNU Affero General Public License version 3, provided that -you comply with its requirements, notably: - -- indicating, in a clear and unambiguous manner, that the software is a - modification of original code; -- retaining Appropriate Legal Notices in the source code and the user - interface; -- keeping any modifications of the software under the terms of the GNU Affero - General Public License version 3, including its Additional Terms pursuant to - its section 7, subsections (b), (c) and (e). - -Following are the applicable Additional Terms for use of the TWAKE software -pursuant to section 7, subsections (b), (c) and (e) of the GNU Affero General -Public License version 3. - -### Additional Terms applicable for TWAKE software - -The following additional terms are applicable to the use, modification and -distribution of TWAKE software: - -**1. Notices and Attribution:** - -The interactive user interfaces in modified source and object code versions of -this program must display Appropriate Legal Notices, as required under Section -5 of the GNU Affero General Public License version 3. - -In accordance with Section 7 and subsection (b) of the GNU Affero General -Public License version 3, these Appropriate Legal Notices consist in the -display, in a clearly legible manner, of the Notice “Twake is powered by -Linagora.” in the TWAKE user interface as well as for any and all type of -outbound messages (e.g. e-mail and meeting requests). - -Retaining this Notice in any and all free and Open Source versions of TWAKE -is mandatory notwithstanding any other terms and conditions. - -If the display of the Appropriate Legal Notices, and/or logos is not reasonably -feasible for technical reasons, the Appropriate Legal Notices must display the -words "Twake is powered by Linagora." - -These Notices can be freely translated and replaced by any notice of strictly -identical meaning in another language according to localization of the software, -provided such notice clearly displays the words “TWAKE” and “LINAGORA”. - -Regardless of the notice language, the Logo/words "TWAKE" must be a clickable -hypertext link that leads directly to the Internet URL https://twake.app. -The Logo/word "LINAGORA" must be a clickable hypertext link that leads directly -to the Internet URL https://linagora.com. - -**2. Use of the TWAKE and LINAGORA trademarks and logos** - -TWAKE™ and LINAGORA™ are registered trademarks of LINAGORA. - -Pursuant to Section 7, subsections (c) and (e) of the GNU Affero General Public -License version 3, this license allows limited use of these trademarks under -the following terms: - -All LINAGORA trademarks, including TWAKE™ and LINAGORA™ logos shall be used by -the licensees and sublicensees for the sole purpose of complying with the -present Additional Terms to the GNU Affero General Public License version 3, -excluding any other purpose without written consent obtained from LINAGORA. - -Using these trademarks without the (TM) trademark notice symbol, removing these -trademarks from the software, modifying these trademarks in any manner except -proportional scaling (under the proviso that such scaling keeps the trademark -clearly legible), or using these trademarks to promote any products or services -commercially, or on product packaging, websites, books, documentation or any -other publication without a written, signed agreement with LINAGORA is strictly -prohibited, and constitutes an infringement of LINAGORA intellectual property -rights over these trademarks. - -Using these trademarks in a way harmful,damaging or detrimental to the value of -the TWAKE brand or any other LINAGORA trademarks, integrity, image, reputation, -and/or goodwill, as determined by LINAGORA, is also strictly prohibited, and -constitutes an infringement of LINAGORA intellectual property rights over these -trademarks as well. - -**Please report any possible violation of the GNU Affero General Public License -version 3, any violation of the hereabove Additional Terms, any infringement -and/or misuse of any TWAKE or LINAGORA trade marks and/or a violation of the -aforementioned Trademark Policy at .** - - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - -Copyright © 2007 Free Software Foundation, Inc. Everyone is -permitted to copy and distribute verbatim copies of this license document, but -changing it is not allowed. - - Preamble - -The GNU Affero General Public License is a free, copyleft license for software -and other kinds of works, specifically designed to ensure cooperation with the -community in the case of network server software. - -The licenses for most software and other practical works are designed to take -away your freedom to share and change the works. By contrast, our General -Public Licenses are intended to guarantee your freedom to share and change all -versions of a program--to make sure it remains free software for all its users. - -When we speak of free software, we are referring to freedom, not price. Our -General Public Licenses are designed to make sure that you have the freedom to -distribute copies of free software (and charge for them if you wish), that you -receive source code or can get it if you want it, that you can change the -software or use pieces of it in new free programs, and that you know you can do -these things. - -Developers that use our General Public Licenses protect your rights with two -steps: (1) assert copyright on the software, and (2) offer you this License -which gives you legal permission to copy, distribute and/or modify the -software. - -A secondary benefit of defending all users' freedom is that improvements made -in alternate versions of the program, if they receive widespread use, become -available for other developers to incorporate. Many developers of free software -are heartened and encouraged by the resulting cooperation. However, in the case -of software used on network servers, this result may fail to come about. The -GNU General Public License permits making a modified version and letting the -public access it on a server without ever releasing its source code to the -public. - -The GNU Affero General Public License is designed specifically to ensure that, -in such cases, the modified source code becomes available to the community. It -requires the operator of a network server to provide the source code of the -modified version running there to the users of that server. Therefore, public -use of a modified version, on a publicly accessible server, gives the public -access to the source code of the modified version. - -An older license, called the Affero General Public License and published by -Affero, was designed to accomplish similar goals. This is a different license, -not a version of the Affero GPL, but Affero has released a new version of the -Affero GPL which permits relicensing under this license. - -The precise terms and conditions for copying, distribution and modification -follow. - - TERMS AND CONDITIONS - -0. Definitions. - -"This License" refers to version 3 of the GNU Affero General Public License. - -"Copyright" also means copyright-like laws that apply to other kinds of works, -such as semiconductor masks. - -"The Program" refers to any copyrightable work licensed under this License. -Each licensee is addressed as "you". "Licensees" and "recipients" may be -individuals or organizations. - -To "modify" a work means to copy from or adapt all or part of the work in a -fashion requiring copyright permission, other than the making of an exact copy. -The resulting work is called a "modified version" of the earlier work or a work -"based on" the earlier work. - -A "covered work" means either the unmodified Program or a work based on the -Program. - -To "propagate" a work means to do anything with it that, without permission, -would make you directly or secondarily liable for infringement under applicable -copyright law, except executing it on a computer or modifying a private copy. -Propagation includes copying, distribution (with or without modification), -making available to the public, and in some countries other activities as well. - -To "convey" a work means any kind of propagation that enables other parties to -make or receive copies. Mere interaction with a user through a computer -network, with no transfer of a copy, is not conveying. - -An interactive user interface displays "Appropriate Legal Notices" to the -extent that it includes a convenient and prominently visible feature that (1) -displays an appropriate copyright notice, and (2) tells the user that there is -no warranty for the work (except to the extent that warranties are provided), -that licensees may convey the work under this License, and how to view a copy -of this License. If the interface presents a list of user commands or options, -such as a menu, a prominent item in the list meets this criterion. - -1. Source Code. - -The "source code" for a work means the preferred form of the work for making -modifications to it. "Object code" means any non-source form of a work. A -"Standard Interface" means an interface that either is an official standard -defined by a recognized standards body, or, in the case of interfaces specified -for a particular programming language, one that is widely used among developers -working in that language. - -The "System Libraries" of an executable work include anything, other than the -work as a whole, that (a) is included in the normal form of packaging a Major -Component, but which is not part of that Major Component, and (b) serves only -to enable use of the work with that Major Component, or to implement a Standard -Interface for which an implementation is available to the public in source code -form. A "Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system (if any) on -which the executable work runs, or a compiler used to produce the work, or an -object code interpreter used to run it. - -The "Corresponding Source" for a work in object code form means all the source -code needed to generate, install, and (for an executable work) run the object -code and to modify the work, including scripts to control those activities. -However, it does not include the work's System Libraries, or general-purpose -tools or generally available free programs which are used unmodified in -performing those activities but which are not part of the work. For example, -Corresponding Source includes interface definition files associated with source -files for the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, such as -by intimate data communication or control flow between those subprograms and -other parts of the work. - -The Corresponding Source need not include anything that users can regenerate -automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same work. - -2. Basic Permissions. - -All rights granted under this License are granted for the term of copyright on -the Program, and are irrevocable provided the stated conditions are met. This -License explicitly affirms your unlimited permission to run the unmodified -Program. The output from running a covered work is covered by this License only -if the output, given its content, constitutes a covered work. This License -acknowledges your rights of fair use or other equivalent, as provided by -copyright law. - -You may make, run and propagate covered works that you do not convey, without -conditions so long as your license otherwise remains in force. You may convey -covered works to others for the sole purpose of having them make modifications -exclusively for you, or provide you with facilities for running those works, -provided that you comply with the terms of this License in conveying all -material for which you do not control copyright. Those thus making or running -the covered works for you must do so exclusively on your behalf, under your -direction and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the -conditions stated below. Sublicensing is not allowed; section 10 makes it -unnecessary. - -3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological measure -under any applicable law fulfilling obligations under article 11 of the WIPO -copyright treaty adopted on 20 December 1996, or similar laws prohibiting or -restricting circumvention of such measures. - -When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention is -effected by exercising rights under this License with respect to the covered -work, and you disclaim any intention to limit operation or modification of the -work as a means of enforcing, against the work's users, your or third parties' -legal rights to forbid circumvention of technological measures. 4. Conveying -Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you receive it, -in any medium, provided that you conspicuously and appropriately publish on -each copy an appropriate copyright notice; keep intact all notices stating that -this License and any non-permissive terms added in accord with section 7 apply -to the code; keep intact all notices of the absence of any warranty; and give -all recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, and you may -offer support or warranty protection for a fee. - -5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to produce it -from the Program, in the form of source code under the terms of section 4, -provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, and - -giving a relevant date. - - b) The work must carry prominent notices stating that it is released under - -this License and any conditions added under section 7. This requirement -modifies the requirement in section 4 to "keep intact all notices". - - c) You must license the entire work, as a whole, under this License to - -anyone who comes into possession of a copy. This License will therefore apply, -along with any applicable section 7 additional terms, to the whole of the work, -and all its parts, regardless of how they are packaged. This License gives no -permission to license the work in any other way, but it does not invalidate -such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - -Appropriate Legal Notices; however, if the Program has interactive interfaces -that do not display Appropriate Legal Notices, your work need not make them do -so. - -A compilation of a covered work with other separate and independent works, -which are not by their nature extensions of the covered work, and which are not -combined with it such as to form a larger program, in or on a volume of a -storage or distribution medium, is called an "aggregate" if the compilation and -its resulting copyright are not used to limit the access or legal rights of the -compilation's users beyond what the individual works permit. Inclusion of a -covered work in an aggregate does not cause this License to apply to the other -parts of the aggregate. - -6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of sections 4 -and 5, provided that you also convey the machine-readable Corresponding Source -under the terms of this License, in one of these ways: - -a) Convey the object code in, or embodied in, a physical product (including a -physical distribution medium), accompanied by the Corresponding Source fixed on -a durable physical medium customarily used for software interchange. - -b) Convey the object code in, or embodied in, a physical product (including a -physical distribution medium), accompanied by a written offer, valid for at -least three years and valid for as long as you offer spare parts or customer -support for that product model, to give anyone who possesses the object code -either (1) a copy of the Corresponding Source for all the software in the -product that is covered by this License, on a durable physical medium -customarily used for software interchange, for a price no more than your -reasonable cost of physically performing this conveying of source, or (2) -access to copy the Corresponding Source from a network server at no charge. - -c) Convey individual copies of the object code with a copy of the written offer -to provide the Corresponding Source. This alternative is allowed only -occasionally and noncommercially, and only if you received the object code with -such an offer, in accord with subsection 6b. - -d) Convey the object code by offering access from a designated place (gratis or -for a charge), and offer equivalent access to the Corresponding Source in the -same way through the same place at no further charge. You need not require -recipients to copy the Corresponding Source along with the object code. If the -place to copy the object code is a network server, the Corresponding Source may -be on a different server (operated by you or a third party) that supports -equivalent copying facilities, provided you maintain clear directions next to -the object code saying where to find the Corresponding Source. Regardless of -what server hosts the Corresponding Source, you remain obligated to ensure that -it is available for as long as needed to satisfy these requirements. - -e) Convey the object code using peer-to-peer transmission, provided you inform -other peers where the object code and Corresponding Source of the work are -being offered to the general public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded from the -Corresponding Source as a System Library, need not be included in conveying the -object code work. - -A "User Product" is either (1) a "consumer product", which means any tangible -personal property which is normally used for personal, family, or household -purposes, or (2) anything designed or sold for incorporation into a dwelling. -In determining whether a product is a consumer product, doubtful cases shall be -resolved in favor of coverage. For a particular product received by a -particular user, "normally used" refers to a typical or common use of that -class of product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected to use, -the product. A product is a consumer product regardless of whether the product -has substantial commercial, industrial or non-consumer uses, unless such uses -represent the only significant mode of use of the product. - -"Installation Information" for a User Product means any methods, procedures, -authorization keys, or other information required to install and execute -modified versions of a covered work in that User Product from a modified -version of its Corresponding Source. The information must suffice to ensure -that the continued functioning of the modified object code is in no case -prevented or interfered with solely because modification has been made. If you -convey an object code work under this section in, or with, or specifically for -use in, a User Product, and the conveying occurs as part of a transaction in -which the right of possession and use of the User Product is transferred to the -recipient in perpetuity or for a fixed term (regardless of how the transaction -is characterized), the Corresponding Source conveyed under this section must be -accompanied by the Installation Information. But this requirement does not -apply if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has been -installed in ROM). - -The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates for a -work that has been modified or installed by the recipient, or for the User -Product in which it has been modified or installed. Access to a network may be -denied when the modification itself materially and adversely affects the -operation of the network or violates the rules and protocols for communication -across the network. - -Corresponding Source conveyed, and Installation Information provided, in accord -with this section must be in a format that is publicly documented (and with an -implementation available to the public in source code form), and must require -no special password or key for unpacking, reading or copying. - -7. Additional Terms. - -"Additional permissions" are terms that supplement the terms of this License by -making exceptions from one or more of its conditions. Additional permissions -that are applicable to the entire Program shall be treated as though they were -included in this License, to the extent that they are valid under applicable -law. If additional permissions apply only to part of the Program, that part may -be used separately under those permissions, but the entire Program remains -governed by this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option remove any -additional permissions from that copy, or from any part of it. (Additional -permissions may be written to require their own removal in certain cases when -you modify the work.) You may place additional permissions on material, added -by you to a covered work, for which you have or can give appropriate copyright -permission. - -Notwithstanding any other provision of this License, for material you add to a -covered work, you may (if authorized by the copyright holders of that material) -supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the terms of - -sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or author - -attributions in that material or in the Appropriate Legal Notices displayed by -works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - -requiring that modified versions of such material be marked in reasonable ways -as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or authors - -of the material; or - - e) Declining to grant rights under trademark law for use of some trade - -names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material by - -anyone who conveys the material (or modified versions of it) with contractual -assumptions of liability to the recipient, for any liability that these -contractual assumptions directly impose on those licensors and authors. - -All other non-permissive additional terms are considered "further restrictions" -within the meaning of section 10. If the Program as you received it, or any -part of it, contains a notice stating that it is governed by this License along -with a term that is a further restriction, you may remove that term. If a -license document contains a further restriction but permits relicensing or -conveying under this License, you may add to a covered work material governed -by the terms of that license document, provided that the further restriction -does not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you must place, -in the relevant source files, a statement of the additional terms that apply to -those files, or a notice indicating where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the form of a -separately written license, or stated as exceptions; the above requirements -apply either way. - -8. Termination. - -You may not propagate or modify a covered work except as expressly provided -under this License. Any attempt otherwise to propagate or modify it is void, -and will automatically terminate your rights under this License (including any -patent licenses granted under the third paragraph of section 11). However, if -you cease all violation of this License, then your license from a particular -copyright holder is reinstated (a) provisionally, unless and until the -copyright holder explicitly and finally terminates your license, and (b) -permanently, if the copyright holder fails to notify you of the violation by -some reasonable means prior to 60 days after the cessation. - -Moreover, your license from a particular copyright holder is reinstated -permanently if the copyright holder notifies you of the violation by some -reasonable means, this is the first time you have received notice of violation -of this License (for any work) from that copyright holder, and you cure the -violation prior to 30 days after your receipt of the notice. - -Termination of your rights under this section does not terminate the licenses -of parties who have received copies or rights from you under this License. If -your rights have been terminated and not permanently reinstated, you do not -qualify to receive new licenses for the same material under section 10. - -9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run a copy -of the Program. Ancillary propagation of a covered work occurring solely as a -consequence of using peer-to-peer transmission to receive a copy likewise does -not require acceptance. However, nothing other than this License grants you -permission to propagate or modify any covered work. These actions infringe -copyright if you do not accept this License. Therefore, by modifying or -propagating a covered work, you indicate your acceptance of this License to do -so. - -10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically receives a -license from the original licensors, to run, modify and propagate that work, -subject to this License. You are not responsible for enforcing compliance by -third parties with this License. - -An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered work -results from an entity transaction, each party to that transaction who receives -a copy of the work also receives whatever licenses to the work the party's -predecessor in interest had or could give under the previous paragraph, plus a -right to possession of the Corresponding Source of the work from the -predecessor in interest, if the predecessor has it or can get it with -reasonable efforts. - -You may not impose any further restrictions on the exercise of the rights -granted or affirmed under this License. For example, you may not impose a -license fee, royalty, or other charge for exercise of rights granted under this -License, and you may not initiate litigation (including a cross-claim or -counterclaim in a lawsuit) alleging that any patent claim is infringed by -making, using, selling, offering for sale, or importing the Program or any -portion of it. - -11. Patents. - -A "contributor" is a copyright holder who authorizes use under this License of -the Program or a work on which the Program is based. The work thus licensed is -called the contributor's "contributor version". - -A contributor's "essential patent claims" are all patent claims owned or -controlled by the contributor, whether already acquired or hereafter acquired, -that would be infringed by some manner, permitted by this License, of making, -using, or selling its contributor version, but do not include claims that would -be infringed only as a consequence of further modification of the contributor -version. For purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of this -License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free patent -license under the contributor's essential patent claims, to make, use, sell, -offer for sale, import and otherwise run, modify and propagate the contents of -its contributor version. - -In the following three paragraphs, a "patent license" is any express agreement -or commitment, however denominated, not to enforce a patent (such as an express -permission to practice a patent or covenant not to sue for patent -infringement). To "grant" such a patent license to a party means to make such -an agreement or commitment not to enforce a patent against the party. - -If you convey a covered work, knowingly relying on a patent license, and the -Corresponding Source of the work is not available for anyone to copy, free of -charge and under the terms of this License, through a publicly available -network server or other readily accessible means, then you must either (1) -cause the Corresponding Source to be so available, or (2) arrange to deprive -yourself of the benefit of the patent license for this particular work, or (3) -arrange, in a manner consistent with the requirements of this License, to -extend the patent license to downstream recipients. "Knowingly relying" means -you have actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work in a -country, would infringe one or more identifiable patents in that country that -you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or arrangement, you -convey, or propagate by procuring conveyance of, a covered work, and grant a -patent license to some of the parties receiving the covered work authorizing -them to use, propagate, modify or convey a specific copy of the covered work, -then the patent license you grant is automatically extended to all recipients -of the covered work and works based on it. - -A patent license is "discriminatory" if it does not include within the scope of -its coverage, prohibits the exercise of, or is conditioned on the non-exercise -of one or more of the rights that are specifically granted under this License. -You may not convey a covered work if you are a party to an arrangement with a -third party that is in the business of distributing software, under which you -make payment to the third party based on the extent of your activity of -conveying the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory patent -license (a) in connection with copies of the covered work conveyed by you (or -copies made from those copies), or (b) primarily for and in connection with -specific products or compilations that contain the covered work, unless you -entered into that arrangement, or that patent license was granted, prior to 28 -March 2007. - -Nothing in this License shall be construed as excluding or limiting any implied -license or other defenses to infringement that may otherwise be available to -you under applicable patent law. - -12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not excuse -you from the conditions of this License. If you cannot convey a covered work so -as to satisfy simultaneously your obligations under this License and any other -pertinent obligations, then as a consequence you may not convey it at all. For -example, if you agree to terms that obligate you to collect a royalty for -further conveying from those to whom you convey the Program, the only way you -could satisfy both those terms and this License would be to refrain entirely -from conveying the Program. - -13. Remote Network Interaction; Use with the GNU General Public License. - -Notwithstanding any other provision of this License, if you modify the Program, -your modified version must prominently offer all users interacting with it -remotely through a computer network (if your version supports such interaction) -an opportunity to receive the Corresponding Source of your version by providing -access to the Corresponding Source from a network server at no charge, through -some standard or customary means of facilitating copying of software. This -Corresponding Source shall include the Corresponding Source for any work -covered by version 3 of the GNU General Public License that is incorporated -pursuant to the following paragraph. - -Notwithstanding any other provision of this License, you have permission to -link or combine any covered work with a work licensed under version 3 of the -GNU General Public License into a single combined work, and to convey the -resulting work. The terms of this License will continue to apply to the part -which is the covered work, but the work with which it is combined will remain -governed by version 3 of the GNU General Public License. 14. Revised Versions -of this License. - -The Free Software Foundation may publish revised and/or new versions of the GNU -Affero General Public License from time to time. Such new versions will be -similar in spirit to the present version, but may differ in detail to address -new problems or concerns. - -Each version is given a distinguishing version number. If the Program specifies -that a certain numbered version of the GNU Affero General Public License "or -any later version" applies to it, you have the option of following the terms -and conditions either of that numbered version or of any later version -published by the Free Software Foundation. If the Program does not specify a -version number of the GNU Affero General Public License, you may choose any -version ever published by the Free Software Foundation. - -If the Program specifies that a proxy can decide which future versions of the -GNU Affero General Public License can be used, that proxy's public statement of -acceptance of a version permanently authorizes you to choose that version for -the Program. - -Later license versions may give you additional or different permissions. -However, no additional obligations are imposed on any author or copyright -holder as a result of your choosing to follow a later version. - -15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE -LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER -PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER -EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE -QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY -COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS -PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, -INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE -THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED -INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE -PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY -HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided above cannot -be given local legal effect according to their terms, reviewing courts shall -apply local law that most closely approximates an absolute waiver of all civil -liability in connection with the Program, unless a warranty or assumption of -liability accompanies a copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -### How to Apply These Terms - -In order to distribute a program under the GNU Affero General Public License -version 3 with the Additional Terms for TWAKE software, attach the following -notices to the program. It is safest to attach them to the start of each source -file to most effectively state the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full notice is found. - -`` - -`Copyright (C) ` - -`This program is free software: you can redistribute it and/or modify it under the -terms of the GNU Affero General Public License as published by the Free Software -Foundation, either version 3 of the License, or (at your option) any later version, -provided you comply with the Additional Terms applicable for TWAKE software by -LINAGORA pursuant to Section 7 of the GNU Affero General Public License, subsections -(b), (c), and (e), pursuant to which you must notably (i) retain the “Twake is powered -by Linagora” notice appended to any type of outbound messages (e.g. e-mail and meeting -requests) as well as in the TWAKE user interface, (ii) retain all hypertext links between -TWAKE and https://twake.app, as well as between LINAGORA and LINAGORA.com, and (iii) refrain -from infringing LINAGORA intellectual property rights over its trademarks and commercial brands. -Other Additional Terms apply, see for more details.` - -`This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Affero General Public License for more details.` - -`You should have received a copy of the GNU Affero General Public License and its applicable Additional -Terms for TWAKE along with this program. If not, see for the GNU Affero -General Public License version 3 and for the Additional Terms -applicable to the TWAKE software.` - -Also add information on how to contact you by electronic and paper mail. - -If your software can interact with users remotely through a computer network, you should also make sure -that it provides a way for users to get its source. For example, if your program is a web application, -its interface could display a "Source" link that leads users to an archive of the code. There are many ways -you could offer source, and different solutions will be better for different programs; see section 13 for -the specific requirements. - -You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright -disclaimer" for the program, if necessary. For more information on this, and how to apply and follow -the GNU AGPL, see . - diff --git a/README.md b/README.md index bcb21e9097..895c047986 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Twake offers all the features for collaboration : - Video call and conferencing - Real time document collaboration - + ## Demo @@ -30,10 +30,12 @@ You can try Twake in SaaS. Or run your own local Twake instance with : +```bash +cd twake +export COMPOSE_FILE=docker-compose.onpremise.yml +docker compose up -d ``` -cd twake -sudo ./start.sh -``` + Twake will be running on http//localhost and by default redirect to https and uses a self-signed certificate. If you want to run http only then set SSL_CERTS=none at docker-compose.yml ## Documentation @@ -61,9 +63,9 @@ Everyone can contribute at their own level, even if they only give a few minutes Install Twake on your machine with docker-compose using the install documentation here : [doc.twake.app/installation](https://doc.twake.app/installation) -### Migration to 2021.Q1.385 +`cd twake; docker-compose -f docker-compose.onpremise.mongo.yml up -d` -If you migrate to the 2021.Q1 version for a 2020.Q4 version or earlier, please follow the documentation at https://github.com/Twake/Twake/tree/main/migration/2020Q3_to_2020Q4 +Twake will be available on port 3000. ## License diff --git a/changelog.md b/changelog.md index 29e46a333f..2548eb86ea 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,149 @@ +# Twake 2022.Q4.1120 + +- Message delivery status 🟢 +- New quote-reply feature ⤴️ +- Notification when someone react to your message 👍 +- New file preview and medias gallery with navigation, caption, and message context 🕶 +- New badge notification system (mention, unread, etc) +- Digest notifications by email ✉️ +- Ability to customize notification sound +- Improved user live status indicator +- See when user was last active on Twake ⏰ +- Big simplification of backend 👩‍💻 + +# Twake 2022.Q3.1065 + +- File and medias channel gallery view 🎞 +- New channel members invitation and management modal ⚙️ +- Fixed connection status of users 🟢 +- New messages search feature on mobile 🔎 +- Fixed bugs and translation #2425 #2424 #2420 #2442 #2436 #2435 + +# Twake 2022.Q3.1050 + +- Open desktop app if present in the system +- Preview public channels before to join them +- Updated [Search anything on Twake](https://github.com/linagora/Twake/issues/1710) +- Started using Tailwindcss for future new design +- Started using Storybooks + +# Twake 2022.Q2.975 + +### Backend + +- [Implemented the list of uploaded in our backend](https://github.com/linagora/Twake/issues/2127) +- [Jump to a message](https://github.com/linagora/Twake/issues/1926) +- [Search for messages](https://github.com/linagora/Twake/issues/1710) +- Generate links previews +- Multiple bug fixes + +### Bug fixed + +- [Fixed thumbnail rotatation when uploaded from mobile](https://github.com/linagora/Twake/issues/2111) +- [Scrolling message feed isn't smooth](https://github.com/linagora/Twake/issues/2039) +- [Position of Close (x) buttons are not consistent](https://github.com/linagora/Twake/issues/2031) +- [Mention user by any namu or identifier](https://github.com/linagora/Twake/issues/2042) +- [Update workspace name reset the logo](https://github.com/linagora/Twake/issues/1950) +- [Empty channel isn't working](https://github.com/linagora/Twake/issues/2146) +- [On Twake desktop I have notifications only inside Twake window and when it's collapsed I don't see them](https://github.com/linagora/Twake/issues/2043) +- [Windows notification has no redirection](https://github.com/linagora/Twake/issues/125) +- [Clicking on push notification does not open the right message](https://github.com/linagora/Twake/issues/396) + +# Twake 2022.Q2.930 + +### Backend + +- Refactoring of how we get services in our backend + +### Bug fixed + +- https://github.com/linagora/Twake/pull/2092 + +# Twake 2022.Q2.910 + +### Messages + +- Copy paste images to message editor fixed +- Large files preview is now available +- Mentions are back in messages +- Giphy, n8n and Jitsi are back + +### General + +- New workspaces parameters page view +- Ability to create and manage plugins from Twake + +### Backend + +- New backend routes to get files and pinned messages of a channel +- New search messages routes + +### Bug fixed + +- Fixed thumbnail generation +- https://github.com/linagora/Twake/issues/2083 +- https://github.com/linagora/Twake/issues/2091 +- https://github.com/linagora/Twake/issues/2095 +- https://github.com/linagora/Twake/issues/2037 +- https://github.com/linagora/Twake/issues/2036 +- https://github.com/linagora/Twake/issues/1918 +- https://github.com/linagora/Twake/issues/2102 + +# Twake 2022.Q1.890 + +### Messages + +- Shows that the last message was deleted on mobile channel list view +- Now we can cancel failed file uploads +- Add spell check to message editor + +### General + +- Save the user last visited companies to open them again after logout +- Fixed magic links +- Show a popup to decide to continue on web or open the mobile app +- Notice users that the company reached the maximum number of users +- Fixed some issues with workspace invitation +- Minor bugs fixed + +# Twake 2022.Q1.874 + +### Messages + +- Faster loading of message feed +- Fix message input issues + +### General + +- Reduce magic links invite urls +- Fix guest popup not visible on paid plans +- Fix company owners and admins not able to manage workspaces +- Fix channels members counters +- Migrate channels to recoil state management for more stable channels (favorite, rename, create, join etc) + +# Twake 2021.Q4.860 + +### Messages + +- Improved message top right menu +- Fixed message sending / edition / reaction / pinned etc, now instant ⚡️ +- User availability indicator 🟢 +- User is writing indicator + +### Workspace parameters + +- Improved integrations management page 🧹 +- Improved workspace users management page 🧹 +- Improved workspace preferences management page 🧹 + +### General + +- A lot of bug fixed, more to come on the 22 of January 🐞 +- Improved Twake loading time (still in progress) ⏰ +- New state management ( recoiljs.org ) on everything except channels and channels members +- Everything except Drive Tasks and Calendar was migrated to node backend 🧹 +- Twake is now working with a simplified docker-compose with only node + mongodb. Note that this works only with messages (no Drive, Calendar or Tasks yet) 🚀 + # Twake 2021.Q3.640 ### Messages diff --git a/twake/.gitignore b/twake/.gitignore index e9b2d3c88e..0ad1d0889e 100644 --- a/twake/.gitignore +++ b/twake/.gitignore @@ -3,6 +3,8 @@ # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 *.DS_Store +*.dccache +.dccache # User-specific stuff: .idea/**/workspace.xml diff --git a/twake/backend/core/src/Twake/Core/Controller/Version.php b/twake/backend/core/src/Twake/Core/Controller/Version.php index c544366535..69f14db8e4 100755 --- a/twake/backend/core/src/Twake/Core/Controller/Version.php +++ b/twake/backend/core/src/Twake/Core/Controller/Version.php @@ -49,10 +49,10 @@ function getVersion(Request $request) "auth_mode" => array_keys($auth), "auth" => $auth, "version" => [ - "current" => /* @VERSION_DETAIL */ "2021.Q4.846", + "current" => /* @VERSION_DETAIL */ "2022.Q4.1120", "minimal" => [ - "web" => /* @MIN_VERSION_WEB */ "2021.Q4.846", - "mobile" => /* @MIN_VERSION_MOBILE */ "2021.Q4.846", + "web" => /* @MIN_VERSION_WEB */ "2022.Q2.975", + "mobile" => /* @MIN_VERSION_MOBILE */ "2022.Q2.975", ] ], "elastic_search_available" => !!$this->container->getParameter("es.host"), diff --git a/twake/backend/core/src/Twake/Drive/Services/DrivePreview.php b/twake/backend/core/src/Twake/Drive/Services/DrivePreview.php index c0377d8193..7113004810 100755 --- a/twake/backend/core/src/Twake/Drive/Services/DrivePreview.php +++ b/twake/backend/core/src/Twake/Drive/Services/DrivePreview.php @@ -45,7 +45,6 @@ public function generatePreview($filename, $file, $path, $ext, $entity = null) $filetype === 'image/gif' || $filetype === 'image/x-icon' || $filetype === 'image/jpeg' || - $filetype === 'image/svg+xml' || $filetype === 'image/tiff' || $filetype === 'image/webp' || $this->isImage($ext)) { diff --git a/twake/backend/core/src/Twake/Drive/Services/Resumable/Resumable.php b/twake/backend/core/src/Twake/Drive/Services/Resumable/Resumable.php index 53b8bb7a0d..7bd5bf6d28 100755 --- a/twake/backend/core/src/Twake/Drive/Services/Resumable/Resumable.php +++ b/twake/backend/core/src/Twake/Drive/Services/Resumable/Resumable.php @@ -114,7 +114,18 @@ public function handleChunk($file_or_url = null, $filename = null, $totalSize = if (is_string($file)) { if (strpos($file, "http://") === 0 || strpos($file, "https://") === 0) { - file_put_contents($chunkFile, fopen($file, 'r')); + try{ + $newContent = fopen($file, 'r', false, stream_context_create(array( + "ssl"=>array( + "verify_peer"=>false, + "verify_peer_name"=>false, + ), + ))); + }catch(\Exception $e){ + error_log("Error while downloading file from url : " . $file); + return; + } + file_put_contents($chunkFile, $newContent); } } else { $this->moveUploadedFile($file['tmp_name'], $chunkFile); diff --git a/twake/backend/core/src/Twake/Market/Services/ApplicationApi.php b/twake/backend/core/src/Twake/Market/Services/ApplicationApi.php index 4bdeeb1c04..a6dc6d9e39 100755 --- a/twake/backend/core/src/Twake/Market/Services/ApplicationApi.php +++ b/twake/backend/core/src/Twake/Market/Services/ApplicationApi.php @@ -64,6 +64,10 @@ public function getAppFromRequest($request, $capabilities = [], $privileges = [] $group_app = $this->doctrine->getRepository("Twake\Workspaces:GroupApp")->findOneBy(Array("app_id" => $application->getId(), "group" => $group_id)); + if($group_app->getPrivileges() === null){ + return $application; + } + if ((!$group_id || !$group_app) && (count($capabilities) > 0 || count($privileges) > 0)) { return Array("error" => "you_need_to_provide_a_valid_group_id_field_in_any_api_request", "group_id" => $group_id); } diff --git a/twake/backend/node/.prettierrc b/twake/backend/node/.prettierrc index 6c836cd533..005b6e4ca0 100644 --- a/twake/backend/node/.prettierrc +++ b/twake/backend/node/.prettierrc @@ -6,4 +6,4 @@ "bracketSpacing": true, "trailingComma": "all", "arrowParens": "avoid" -} \ No newline at end of file +} diff --git a/twake/backend/node/config/custom-environment-variables.json b/twake/backend/node/config/custom-environment-variables.json index e4b77b29a0..578963483e 100644 --- a/twake/backend/node/config/custom-environment-variables.json +++ b/twake/backend/node/config/custom-environment-variables.json @@ -62,10 +62,20 @@ "flushInterval": "SEARCH_ES_FLUSHINTERVAL" } }, - "pubsub": { + "message-queue": { "type": "PUBSUB_TYPE", "amqp": { "urls": "PUBSUB_URLS" } + }, + "pusbub": { + "//": "//deprecated", + "type": "PUBSUB_TYPE", + "amqp": { + "urls": "PUBSUB_URLS" + } + }, + "plugins": { + "server": "PLUGINS_SERVER" } } diff --git a/twake/backend/node/config/default.json b/twake/backend/node/config/default.json index 10d8f8451b..bcfbdad29b 100644 --- a/twake/backend/node/config/default.json +++ b/twake/backend/node/config/default.json @@ -2,6 +2,12 @@ "general": { "help_url": false, "pricing_plan_url": "", + "app_download_url": "https://twake.app/download", + "mobile": { + "mobile_redirect": "mobile.twake.app", + "mobile_appstore": "https://apps.apple.com/fr/app/twake/id1588764852?l=en", + "mobile_googleplay": "https://play.google.com/store/apps/details?id=com.twake.twake&gl=FR" + }, "accounts": { "_type": "console", "type": "internal", @@ -9,11 +15,11 @@ "disable_account_creation": false }, "console": { - "account_management_url": "http://web.twake-console.local/profile", + "account_management_url": "http://web.twake-console.local/profile?company-code={company_id}", "authority": "http://auth.example.com/", "client_id": "twakeweb", - "collaborators_management_url": "http://web.twake-console.local/compaies/{company_id}/users", - "company_management_url": "http://web.twake-console.local/companies" + "collaborators_management_url": "http://web.twake-console.local/compaies/{company_id}/users?company-code={company_id}", + "company_management_url": "http://web.twake-console.local/companies?company-code={company_id}" } } }, @@ -21,6 +27,7 @@ "_type": "remote", "type": "internal", "remote": { + "new_console": false, "username": "", "password": "12345678", "url": "https://some-remote-console-url/", @@ -98,7 +105,7 @@ "delay": 200 } }, - "pubsub": { + "message-queue": { "// possible 'type' values are": "'amqp' or 'local'", "type": "amqp", "amqp": { @@ -133,6 +140,19 @@ "path": "/storage/" } }, + "plugins": { + "server": "plugins:3100" + }, + "knowledge-graph": { + "endpoint": "http://host-gateway:8888", + "use": false, + "forwarded_companies": [] + }, + "email-pusher": { + "endpoint": "https://api.smtp2go.com/v3/email/send", + "api_key": "secret", + "sender": "noreply@twake.app" + }, "services": [ "auth", "push", @@ -140,14 +160,15 @@ "webserver", "websocket", "database", + "cron", "search", - "pubsub", + "message-queue", "realtime", "phpnode", "tracker", "general", "user", - "applicationsapi", + "applications-api", "applications", "channels", "notifications", @@ -156,10 +177,11 @@ "workspaces", "console", "previews", - "platform-services", "counter", "statistics", "cron", - "online" + "online", + "knowledge-graph", + "email-pusher" ] } diff --git a/twake/backend/node/config/test.json b/twake/backend/node/config/test.json index e5f3d5efae..65aadc6f85 100644 --- a/twake/backend/node/config/test.json +++ b/twake/backend/node/config/test.json @@ -8,10 +8,13 @@ "contactPoints": ["scylladb:9042"], "wait": true, "retries": 50, - "delay": 500 + "delay": 500, + "queryOptions": { + "consistency": 1 + } } }, - "pubsub": { + "message-queue": { "type": "amqp", "amqp": { "urls": ["amqp://guest:guest@rabbitmq:5672"] diff --git a/twake/backend/node/package-lock.json b/twake/backend/node/package-lock.json index ca4b527d1b..4506fda42a 100644 --- a/twake/backend/node/package-lock.json +++ b/twake/backend/node/package-lock.json @@ -1,145 +1,30 @@ { "name": "@twake/twake-backend", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "@twake/twake-backend", - "version": "1.0.0", - "license": "ISC", - "dependencies": { - "@elastic/elasticsearch": "7", - "@sentry/node": "^6.13.3", - "@sentry/tracing": "^6.13.3", - "amqp-connection-manager": "^3.7.0", - "amqplib": "^0.7.1", - "analytics-node": "^5.0.0", - "axios": "^0.21.3", - "bcrypt": "^5.0.1", - "cassandra-driver": "^4.6.0", - "class-transformer": "^0.3.1", - "cli-table": "^0.3.6", - "config": "^3.3.2", - "deep-object-diff": "^1.1.0", - "fastify": "3.22.1", - "fastify-cors": "^4.1.0", - "fastify-formbody": "^5.0.0", - "fastify-jwt": "^2.2.0", - "fastify-multipart": "4.0.3", - "fastify-plugin": "^2.3.4", - "fastify-sensible": "^3.0.1", - "fastify-swagger": "^4.12.6", - "fastify-websocket": "^2.0.11", - "generate-password": "^1.6.0", - "lodash": "^4.17.21", - "match-all": "^1.2.6", - "minio": "^7.0.18", - "moment": "^2.29.1", - "mongodb": "^4.1.0", - "multistream": "^4.1.0", - "node-cron": "^3.0.0", - "node-fetch": "^2.6.5", - "node-uuid": "^1.4.8", - "ora": "^5.4.0", - "pdf2pic": "^2.1.4", - "pino": "^6.8.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^6.6.3", - "sharp": "^0.29.0", - "socket.io": "^2.3.0", - "socket.io-client": "^2.3.1", - "socket.io-redis": "^5.4.0", - "socketio-jwt": "^4.6.2", - "unoconv-promise": "^1.0.8", - "uuid": "^8.3.2", - "uuid-time": "^1.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "twake-cli": "bin/twake-cli" - }, - "devDependencies": { - "@babel/core": "^7.11.6", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-decorators": "^7.10.5", - "@babel/preset-env": "^7.11.5", - "@babel/preset-typescript": "^7.10.4", - "@types/amqp-connection-manager": "^2.0.10", - "@types/analytics-node": "^3.1.5", - "@types/bcrypt": "^5.0.0", - "@types/busboy": "^0.2.3", - "@types/chai": "^4.2.12", - "@types/cli-table": "^0.3.0", - "@types/config": "0.0.36", - "@types/eslint": "^7.2.3", - "@types/fastify-multipart": "^0.7.0", - "@types/jest": "^26.0.14", - "@types/lodash": "^4.14.165", - "@types/minio": "^7.0.7", - "@types/mongodb": "^4.0.7", - "@types/node": "^14.11.2", - "@types/node-cron": "^3.0.0", - "@types/node-fetch": "^2.5.10", - "@types/node-uuid": "^0.0.28", - "@types/pdf-image": "^2.0.1", - "@types/pino": "^6.3.2", - "@types/sharp": "^0.28.5", - "@types/socket.io": "^2.1.11", - "@types/socket.io-client": "^1.4.34", - "@types/socket.io-redis": "^1.0.26", - "@types/supertest": "2.0.4", - "@types/uuid": "^8.3.0", - "@types/ws": "^7.2.7", - "@typescript-eslint/eslint-plugin": "^4.2.0", - "@typescript-eslint/parser": "^4.2.0", - "babel-jest": "^26.5.2", - "babel-plugin-parameter-decorator": "^1.0.16", - "chai": "^4.2.0", - "eslint": "^7.10.0", - "eslint-config-prettier": "^6.15.0", - "eslint-plugin-prettier": "^3.1.4", - "form-auto-content": "^2.2.0", - "jest": "^26.6.3", - "nodemon": "2.0.4", - "pino-pretty": "^4.7.1", - "prettier": "^2.1.2", - "rimraf": "^3.0.2", - "supertest": "4.0.2", - "ts-jest": "^26.4.0", - "ts-node": "^9.0.0", - "ts-node-dev": "^1.1.8", - "tsc-watch": "^4.2.9", - "typescript": "^4.0.3" - } - }, - "node_modules/@babel/code-frame": { + "dependencies": { + "@babel/code-frame": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", "dev": true, - "dependencies": { + "requires": { "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/compat-data": { + "@babel/compat-data": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/core": { + "@babel/core": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", "dev": true, - "dependencies": { + "requires": { "@babel/code-frame": "^7.14.5", "@babel/generator": "^7.15.0", "@babel/helper-compilation-targets": "^7.15.0", @@ -156,113 +41,109 @@ "semver": "^6.3.0", "source-map": "^0.5.0" }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, - "node_modules/@babel/generator": { + "@babel/generator": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.15.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, - "node_modules/@babel/helper-annotate-as-pure": { + "@babel/helper-annotate-as-pure": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-explode-assignable-expression": "^7.14.5", "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets": { + "@babel/helper-compilation-targets": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", "dev": true, - "dependencies": { + "requires": { "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", "browserslist": "^4.16.6", "semver": "^6.3.0" }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "node_modules/@babel/helper-create-class-features-plugin": { + "@babel/helper-create-class-features-plugin": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-function-name": "^7.14.5", "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-split-export-declaration": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { + "@babel/helper-create-regexp-features-plugin": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "regexpu-core": "^4.7.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-define-polyfill-provider": { + "@babel/helper-define-polyfill-provider": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-compilation-targets": "^7.13.0", "@babel/helper-module-imports": "^7.12.13", "@babel/helper-plugin-utils": "^7.13.0", @@ -272,90 +153,77 @@ "resolve": "^1.14.2", "semver": "^6.1.2" }, - "peerDependencies": { - "@babel/core": "^7.4.0-0" + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, - "node_modules/@babel/helper-explode-assignable-expression": { + "@babel/helper-explode-assignable-expression": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-function-name": { + "@babel/helper-function-name": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-get-function-arity": "^7.14.5", "@babel/template": "^7.14.5", "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-get-function-arity": { + "@babel/helper-get-function-arity": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { + "@babel/helper-hoist-variables": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-member-expression-to-functions": { + "@babel/helper-member-expression-to-functions": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { + "@babel/helper-module-imports": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-transforms": { + "@babel/helper-module-transforms": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-module-imports": "^7.14.5", "@babel/helper-replace-supers": "^7.15.0", "@babel/helper-simple-access": "^7.14.8", @@ -364,751 +232,563 @@ "@babel/template": "^7.14.5", "@babel/traverse": "^7.15.0", "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-optimise-call-expression": { + "@babel/helper-optimise-call-expression": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-plugin-utils": { + "@babel/helper-plugin-utils": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/helper-remap-async-to-generator": { + "@babel/helper-remap-async-to-generator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-wrap-function": "^7.14.5", "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-replace-supers": { + "@babel/helper-replace-supers": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-member-expression-to-functions": "^7.15.0", "@babel/helper-optimise-call-expression": "^7.14.5", "@babel/traverse": "^7.15.0", "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-simple-access": { + "@babel/helper-simple-access": { "version": "7.14.8", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.8" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "@babel/helper-skip-transparent-expression-wrappers": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-split-export-declaration": { + "@babel/helper-split-export-declaration": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", "dev": true, - "dependencies": { + "requires": { "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { + "@babel/helper-validator-identifier": { "version": "7.14.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/helper-validator-option": { + "@babel/helper-validator-option": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } + "dev": true }, - "node_modules/@babel/helper-wrap-function": { + "@babel/helper-wrap-function": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-function-name": "^7.14.5", "@babel/template": "^7.14.5", "@babel/traverse": "^7.14.5", "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/helpers": { + "@babel/helpers": { "version": "7.15.3", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", "dev": true, - "dependencies": { + "requires": { "@babel/template": "^7.14.5", "@babel/traverse": "^7.15.0", "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" } }, - "node_modules/@babel/highlight": { + "@babel/highlight": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, - "engines": { - "node": ">=6.9.0" + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "node_modules/@babel/parser": { + "@babel/parser": { "version": "7.15.3", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } + "dev": true }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", "@babel/plugin-proposal-optional-chaining": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { + "@babel/plugin-proposal-async-generator-functions": { "version": "7.14.9", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-remap-async-to-generator": "^7.14.5", "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-class-properties": { + "@babel/plugin-proposal-class-properties": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-class-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-class-static-block": { + "@babel/plugin-proposal-class-static-block": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-class-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" } }, - "node_modules/@babel/plugin-proposal-decorators": { + "@babel/plugin-proposal-decorators": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz", "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-class-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-decorators": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-dynamic-import": { + "@babel/plugin-proposal-dynamic-import": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-export-namespace-from": { + "@babel/plugin-proposal-export-namespace-from": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-json-strings": { + "@babel/plugin-proposal-json-strings": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "@babel/plugin-proposal-logical-assignment-operators": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-numeric-separator": { + "@babel/plugin-proposal-numeric-separator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { + "@babel/plugin-proposal-object-rest-spread": { "version": "7.14.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "dev": true, - "dependencies": { + "requires": { "@babel/compat-data": "^7.14.7", "@babel/helper-compilation-targets": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-transform-parameters": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "@babel/plugin-proposal-optional-catch-binding": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-optional-chaining": { + "@babel/plugin-proposal-optional-chaining": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-methods": { + "@babel/plugin-proposal-private-methods": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-class-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { + "@babel/plugin-proposal-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-create-class-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "@babel/plugin-proposal-unicode-property-regex": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { + "@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-bigint": { + "@babel/plugin-syntax-bigint": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-properties": { + "@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { + "@babel/plugin-syntax-class-static-block": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-decorators": { + "@babel/plugin-syntax-decorators": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz", "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { + "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { + "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { + "@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-json-strings": { + "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "@babel/plugin-syntax-logical-assignment-operators": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "@babel/plugin-syntax-nullish-coalescing-operator": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { + "@babel/plugin-syntax-numeric-separator": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { + "@babel/plugin-syntax-object-rest-spread": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "@babel/plugin-syntax-optional-catch-binding": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { + "@babel/plugin-syntax-optional-chaining": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { + "@babel/plugin-syntax-private-property-in-object": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { + "@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { + "@babel/plugin-syntax-typescript": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { + "@babel/plugin-transform-arrow-functions": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { + "@babel/plugin-transform-async-to-generator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-module-imports": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-remap-async-to-generator": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { + "@babel/plugin-transform-block-scoped-functions": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-block-scoping": { + "@babel/plugin-transform-block-scoping": { "version": "7.15.3", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes": { + "@babel/plugin-transform-classes": { "version": "7.14.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-annotate-as-pure": "^7.14.5", "@babel/helper-function-name": "^7.14.5", "@babel/helper-optimise-call-expression": "^7.14.5", @@ -1116,458 +796,284 @@ "@babel/helper-replace-supers": "^7.14.5", "@babel/helper-split-export-declaration": "^7.14.5", "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-computed-properties": { + "@babel/plugin-transform-computed-properties": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-destructuring": { + "@babel/plugin-transform-destructuring": { "version": "7.14.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { + "@babel/plugin-transform-dotall-regex": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { + "@babel/plugin-transform-duplicate-keys": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { + "@babel/plugin-transform-exponentiation-operator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-for-of": { + "@babel/plugin-transform-for-of": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-function-name": { + "@babel/plugin-transform-function-name": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-function-name": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-literals": { + "@babel/plugin-transform-literals": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { + "@babel/plugin-transform-member-expression-literals": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-amd": { + "@babel/plugin-transform-modules-amd": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-module-transforms": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { + "@babel/plugin-transform-modules-commonjs": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-module-transforms": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-simple-access": "^7.14.8", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { + "@babel/plugin-transform-modules-systemjs": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-hoist-variables": "^7.14.5", "@babel/helper-module-transforms": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-identifier": "^7.14.5", "babel-plugin-dynamic-import-node": "^2.3.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-modules-umd": { + "@babel/plugin-transform-modules-umd": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-module-transforms": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.14.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-new-target": { + "@babel/plugin-transform-new-target": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-object-super": { + "@babel/plugin-transform-object-super": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-replace-supers": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-parameters": { + "@babel/plugin-transform-parameters": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-property-literals": { + "@babel/plugin-transform-property-literals": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-regenerator": { + "@babel/plugin-transform-regenerator": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", "dev": true, - "dependencies": { + "requires": { "regenerator-transform": "^0.14.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { + "@babel/plugin-transform-reserved-words": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { + "@babel/plugin-transform-shorthand-properties": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-spread": { + "@babel/plugin-transform-spread": { "version": "7.14.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { + "@babel/plugin-transform-sticky-regex": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-template-literals": { + "@babel/plugin-transform-template-literals": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { + "@babel/plugin-transform-typeof-symbol": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typescript": { + "@babel/plugin-transform-typescript": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz", "integrity": "sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-class-features-plugin": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-typescript": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { + "@babel/plugin-transform-unicode-escapes": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { + "@babel/plugin-transform-unicode-regex": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", "dev": true, - "dependencies": { + "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env": { + "@babel/preset-env": { "version": "7.15.0", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", "dev": true, - "dependencies": { + "requires": { "@babel/compat-data": "^7.15.0", "@babel/helper-compilation-targets": "^7.15.0", "@babel/helper-plugin-utils": "^7.14.5", @@ -1642,15672 +1148,13 @@ "core-js-compat": "^3.16.0", "semver": "^6.3.0" }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz", - "integrity": "sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-transform-typescript": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@cnakazawa/watch": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", - "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", - "dev": true, - "dependencies": { - "exec-sh": "^0.3.2", - "minimist": "^1.2.0" - }, - "bin": { - "watch": "cli.js" - }, - "engines": { - "node": ">=0.1.95" - } - }, - "node_modules/@elastic/elasticsearch": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.14.0.tgz", - "integrity": "sha512-BlxqykcNtdBxo0mF7UQ1OsUxoVOOnEaeF70u2N4jpePih9paCOOotTWfFSDrtEw0TWv1CZlzCGD3TD5+8ASx8A==", - "dependencies": { - "debug": "^4.3.1", - "hpagent": "^0.1.1", - "ms": "^2.1.3", - "secure-json-parse": "^2.4.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@fastify/ajv-compiler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz", - "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==", - "dependencies": { - "ajv": "^6.12.6" - } - }, - "node_modules/@hapi/bourne": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", - "integrity": "sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==", - "dev": true - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", - "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^26.6.2", - "jest-util": "^26.6.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/console/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/console/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/console/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/console/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz", - "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==", - "dev": true, - "dependencies": { - "@jest/console": "^26.6.2", - "@jest/reporters": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/transform": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.6.2", - "jest-config": "^26.6.3", - "jest-haste-map": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.2", - "jest-resolve-dependencies": "^26.6.3", - "jest-runner": "^26.6.3", - "jest-runtime": "^26.6.3", - "jest-snapshot": "^26.6.2", - "jest-util": "^26.6.2", - "jest-validate": "^26.6.2", - "jest-watcher": "^26.6.2", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/core/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/core/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/core/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/core/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/environment": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz", - "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "jest-mock": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/fake-timers": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz", - "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@sinonjs/fake-timers": "^6.0.1", - "@types/node": "*", - "jest-message-util": "^26.6.2", - "jest-mock": "^26.6.2", - "jest-util": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/globals": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz", - "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==", - "dev": true, - "dependencies": { - "@jest/environment": "^26.6.2", - "@jest/types": "^26.6.2", - "expect": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/reporters": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz", - "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/transform": "^26.6.2", - "@jest/types": "^26.6.2", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.6.2", - "jest-resolve": "^26.6.2", - "jest-util": "^26.6.2", - "jest-worker": "^26.6.2", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^7.0.0" - }, - "engines": { - "node": ">= 10.14.2" - }, - "optionalDependencies": { - "node-notifier": "^8.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/reporters/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/reporters/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/reporters/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/source-map": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz", - "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/test-result": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", - "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", - "dev": true, - "dependencies": { - "@jest/console": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz", - "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^26.6.2", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.6.2", - "jest-runner": "^26.6.3", - "jest-runtime": "^26.6.3" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/transform": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", - "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", - "dev": true, - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.6.2", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.6.2", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.6.2", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/transform/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/transform/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/transform/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/transform/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/transform/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/transform/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/@jest/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@jest/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz", - "integrity": "sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==", - "dependencies": { - "detect-libc": "^1.0.3", - "https-proxy-agent": "^5.0.0", - "make-dir": "^3.1.0", - "node-fetch": "^2.6.1", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "rimraf": "^3.0.2", - "semver": "^7.3.4", - "tar": "^6.1.0" - }, - "bin": { - "node-pre-gyp": "bin/node-pre-gyp" - } - }, - "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@segment/loosely-validate-event": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz", - "integrity": "sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw==", - "dependencies": { - "component-type": "^1.2.1", - "join-component": "^1.1.0" - } - }, - "node_modules/@sentry/core": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.3.tgz", - "integrity": "sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA==", - "dependencies": { - "@sentry/hub": "6.13.3", - "@sentry/minimal": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/hub": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.3.tgz", - "integrity": "sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw==", - "dependencies": { - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/minimal": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.3.tgz", - "integrity": "sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw==", - "dependencies": { - "@sentry/hub": "6.13.3", - "@sentry/types": "6.13.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/node": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.3.tgz", - "integrity": "sha512-ZeZSw+TcPcf4e0j7iEqNMtoVmz+WFW/TEoGokXIwysZqSgchKdAXDHqn+CqUqFan7d76JcJmzztAUK2JruQ2Kg==", - "license": "BSD-3-Clause", - "dependencies": { - "@sentry/core": "6.13.3", - "@sentry/hub": "6.13.3", - "@sentry/tracing": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/tracing": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.3.tgz", - "integrity": "sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q==", - "license": "MIT", - "dependencies": { - "@sentry/hub": "6.13.3", - "@sentry/minimal": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/types": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.3.tgz", - "integrity": "sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@sentry/utils": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.3.tgz", - "integrity": "sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag==", - "dependencies": { - "@sentry/types": "6.13.3", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dev": true, - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/amqp-connection-manager": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@types/amqp-connection-manager/-/amqp-connection-manager-2.0.12.tgz", - "integrity": "sha512-2GX1jG6ECpEXQF0X68gTTZc8MQ8GA0dM2mAd1irTpWlKzGKlGzCBtb1YnqLHozNNsoLtGI6UXSp0q06jU1LA6g==", - "dev": true, - "dependencies": { - "@types/amqplib": "*" - } - }, - "node_modules/@types/amqplib": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.2.tgz", - "integrity": "sha512-p+TFLzo52f8UanB+Nq6gyUi65yecAcRY3nYowU6MPGFtaJvEDxcnFWrxssSTkF+ts1W3zyQDvgVICLQem5WxRA==", - "dev": true, - "dependencies": { - "@types/bluebird": "*", - "@types/node": "*" - } - }, - "node_modules/@types/analytics-node": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.5.tgz", - "integrity": "sha512-zSqNpyzF3hcweslf7ttqB03iZvxtymUh820SAXaFhox5Y5Qa7bYmrdOi4IW050OHrKmtq4SE4kE1XeE1mK+zrQ==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.1.15", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz", - "integrity": "sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/bcrypt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz", - "integrity": "sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/bluebird": { - "version": "3.5.36", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz", - "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", - "dev": true - }, - "node_modules/@types/busboy": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@types/busboy/-/busboy-0.2.4.tgz", - "integrity": "sha512-f+ZCVjlcN8JW/zf3iR0GqO4gjOUlltMTtZjn+YR1mlK+MVu6esTiIecO0/GQlmYQPQLdBnc7+5vG3Xb+SkvFLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/chai": { - "version": "4.2.21", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz", - "integrity": "sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg==", - "dev": true - }, - "node_modules/@types/cli-table": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@types/cli-table/-/cli-table-0.3.0.tgz", - "integrity": "sha512-QnZUISJJXyhyD6L1e5QwXDV/A5i2W1/gl6D6YMc8u0ncPepbv/B4w3S+izVvtAg60m6h+JP09+Y/0zF2mojlFQ==", - "dev": true - }, - "node_modules/@types/component-emitter": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", - "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==", - "dev": true - }, - "node_modules/@types/config": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@types/config/-/config-0.0.36.tgz", - "integrity": "sha512-EoAeT1MyFWh2BJvBDEFInY714bQBbHOAucqxqqhprhbBFqr+B7fuN5T9CJqUIGDzvwubnKKRqmSo6yPo0aSpNw==", - "dev": true - }, - "node_modules/@types/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", - "dev": true - }, - "node_modules/@types/engine.io": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.7.tgz", - "integrity": "sha512-qNjVXcrp+1sS8YpRUa714r0pgzOwESdW5UjHL7D/2ZFdBX0BXUXtg1LUrp+ylvqbvMcMWUy73YpRoxPN2VoKAQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz", - "integrity": "sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A==", - "dev": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.50", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", - "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", - "dev": true - }, - "node_modules/@types/fastify-multipart": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@types/fastify-multipart/-/fastify-multipart-0.7.0.tgz", - "integrity": "sha512-dKK9S8nBesXhSfUlgyGE7mNJ5a1TxiBeIalJFdPbUj5bJywgjo3ixpm+LcIpTK2UwQ10OWptny/Kjc3GprREtg==", - "deprecated": "This is a stub types definition. fastify-multipart provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "fastify-multipart": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "26.0.24", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz", - "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==", - "dev": true, - "dependencies": { - "jest-diff": "^26.0.0", - "pretty-format": "^26.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/jsonwebtoken": { - "version": "8.5.5", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.5.tgz", - "integrity": "sha512-OGqtHQ7N5/Ap/TUwO6IgHDuLiAoTmHhGpNvgkCm/F4N6pKzx/RBSfr2OXZSwC6vkfnsEdb6+7DNZVtiXiwdwFw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.14.172", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz", - "integrity": "sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw==", - "dev": true - }, - "node_modules/@types/long": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", - "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" - }, - "node_modules/@types/minio": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/minio/-/minio-7.0.9.tgz", - "integrity": "sha512-aMalbSDDB+TV9m3fVMD4E2vJR3XVAtOcf9t5Iq+PHnc5D0ti3LMXjaxGKXmllicliaBrh0gzURLrs44n/Jl43g==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mongodb": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz", - "integrity": "sha512-lPUYPpzA43baXqnd36cZ9xxorprybxXDzteVKCPAdp14ppHtFJHnXYvNpmBvtMUTb5fKXVv6sVbzo1LHkWhJlw==", - "deprecated": "mongodb provides its own types. @types/mongodb is no longer needed.", - "dev": true, - "dependencies": { - "mongodb": "*" - } - }, - "node_modules/@types/node": { - "version": "14.17.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.11.tgz", - "integrity": "sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==" - }, - "node_modules/@types/node-cron": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.0.tgz", - "integrity": "sha512-RNBIyVwa/1v2r8/SqK8tadH2sJlFRAo5Ghac/cOcCv4Kp94m0I03UmAh9WVhCqS9ZdB84dF3x47p9aTw8E4c4A==", - "dev": true - }, - "node_modules/@types/node-fetch": { - "version": "2.5.12", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz", - "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "form-data": "^3.0.0" - } - }, - "node_modules/@types/node-uuid": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@types/node-uuid/-/node-uuid-0.0.28.tgz", - "integrity": "sha1-QWVbXOY7LzN0xOgmtN0h5ykFjj0=", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/pdf-image": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/pdf-image/-/pdf-image-2.0.1.tgz", - "integrity": "sha512-WSG+F90yd53I2iA3/MiRolRmP0hT0GLkfdq2CYg1sW1AmsWK9bitc9v0EaakkMvFebESzoU/P4vsUhYnDz/OYw==", - "dev": true - }, - "node_modules/@types/pino": { - "version": "6.3.11", - "resolved": "https://registry.npmjs.org/@types/pino/-/pino-6.3.11.tgz", - "integrity": "sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/pino-pretty": "*", - "@types/pino-std-serializers": "*", - "sonic-boom": "^2.1.0" - } - }, - "node_modules/@types/pino-pretty": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-4.7.1.tgz", - "integrity": "sha512-l1ntNXdpVWsnPYUk5HyO5Lxfr38zLCgxVfEn/9Zhhm+nGF04/BiIou/m8XPwvoVZLV+livUo79VdHXMJPfUYxA==", - "dev": true, - "dependencies": { - "@types/pino": "*" - } - }, - "node_modules/@types/pino-std-serializers": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-2.4.1.tgz", - "integrity": "sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", - "dev": true - }, - "node_modules/@types/redis": { - "version": "2.8.31", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", - "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/sharp": { - "version": "0.28.6", - "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.28.6.tgz", - "integrity": "sha512-AjKjo5vk5mkcTrWL0U1zFUdCp/uqLebvbe7ezAJx0tgp6ST9JmfsYK1q1lpjfPM5S1YQ1wr5uboPSu2S8UO9yw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/socket.io": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz", - "integrity": "sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg==", - "dev": true, - "dependencies": { - "@types/engine.io": "*", - "@types/node": "*", - "@types/socket.io-parser": "*" - } - }, - "node_modules/@types/socket.io-client": { - "version": "1.4.36", - "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", - "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==", - "dev": true - }, - "node_modules/@types/socket.io-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz", - "integrity": "sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew==", - "deprecated": "This is a stub types definition. socket.io-parser provides its own type definitions, so you do not need this installed.", - "dev": true, - "dependencies": { - "socket.io-parser": "*" - } - }, - "node_modules/@types/socket.io-redis": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@types/socket.io-redis/-/socket.io-redis-1.0.27.tgz", - "integrity": "sha512-oyJPDjn5Dnci3wZD2bd1jfPsJkqvTwoNGpOIF+/+P45cOn4zrYsUO9mcGN/shoxIlCz6bcdRhSRXWwZFGQc1PA==", - "dev": true, - "dependencies": { - "@types/redis": "*", - "@types/socket.io": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", - "dev": true - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "node_modules/@types/superagent": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.12.tgz", - "integrity": "sha512-1GQvD6sySQPD6p9EopDFI3f5OogdICl1sU/2ij3Esobz/RtL9fWZZDPmsuv7eiy5ya+XNiPAxUcI3HIUTJa+3A==", - "dev": true, - "dependencies": { - "@types/cookiejar": "*", - "@types/node": "*" - } - }, - "node_modules/@types/supertest": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.4.tgz", - "integrity": "sha512-0TvOJ+6XVMSImgqc2ClNllfVffCxHQhFbsbwOGzGTjdFydoaG052LPqnP8SnmSlnokOcQiPPcbz+Yi30LxWPyA==", - "dev": true, - "dependencies": { - "@types/superagent": "*" - } - }, - "node_modules/@types/uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==", - "dev": true - }, - "node_modules/@types/webidl-conversions": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz", - "integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q==" - }, - "node_modules/@types/whatwg-url": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz", - "integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==", - "dependencies": { - "@types/node": "*", - "@types/webidl-conversions": "*" - } - }, - "node_modules/@types/ws": { - "version": "7.4.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", - "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "15.0.14", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", - "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz", - "integrity": "sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.29.3", - "@typescript-eslint/scope-manager": "4.29.3", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz", - "integrity": "sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.29.3", - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/typescript-estree": "4.29.3", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz", - "integrity": "sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.29.3", - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/typescript-estree": "4.29.3", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz", - "integrity": "sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/visitor-keys": "4.29.3" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz", - "integrity": "sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz", - "integrity": "sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.3", - "@typescript-eslint/visitor-keys": "4.29.3", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz", - "integrity": "sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.3", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@zxing/text-encoding": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz", - "integrity": "sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==", - "optional": true - }, - "node_modules/abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", - "dev": true - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "node_modules/abstract-logging": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", - "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==" - }, - "node_modules/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dependencies": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/adm-zip": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.5.tgz", - "integrity": "sha512-IWwXKnCbirdbyXSfUDvCCrmYrOHANRZcc8NcRrvTlIApdl7PwE9oGcsYvNeJPAVY1M+70b4PxXGKIf8AEuiQ6w==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "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" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amqp-connection-manager": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/amqp-connection-manager/-/amqp-connection-manager-3.7.0.tgz", - "integrity": "sha512-pWlrXVQNnSV9Jsewq6wnZjddzlHI/gZroDdmMEYfsqaAUa2V2ENCXbDdoi0r/GVesxueY/Yb8nBO024lfdtdPQ==", - "license": "MIT", - "dependencies": { - "promise-breaker": "^5.0.0" - }, - "engines": { - "node": ">=10.0.0", - "npm": ">5.0.0" - }, - "peerDependencies": { - "amqplib": "*" - } - }, - "node_modules/amqplib": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.7.1.tgz", - "integrity": "sha512-KePK3tTOLGU4emTo+PwSDMbc123jrxo13FpRpim1LzJoSlQrIBB2/kMeCC40jK/Zb0olHGaABjLqXDsdK46iLA==", - "dependencies": { - "bitsyntax": "~0.1.0", - "bluebird": "^3.7.2", - "buffer-more-ints": "~1.0.0", - "readable-stream": "1.x >=1.1.9", - "safe-buffer": "~5.2.1", - "url-parse": "~1.5.1" - }, - "engines": { - "node": ">=0.8 <=15" - } - }, - "node_modules/analytics-node": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/analytics-node/-/analytics-node-5.0.0.tgz", - "integrity": "sha512-eU/lPK6V3hmmv7hnJ8762zExL7WvcpVeBL6RgGZ8yQZQewk08VbbHk0M5GAlhruyh0ZT+/IBPW3Q/SYVhjexNQ==", - "dependencies": { - "@segment/loosely-validate-event": "^2.0.0", - "axios": "^0.21.1", - "axios-retry": "^3.0.2", - "lodash.isstring": "^4.0.1", - "md5": "^2.2.1", - "ms": "^2.0.0", - "remove-trailing-slash": "^0.1.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "dev": true, - "dependencies": { - "string-width": "^3.0.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" - }, - "node_modules/are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/are-we-there-yet/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "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" - } - }, - "node_modules/are-we-there-yet/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/are-we-there-yet/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/args": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/args/-/args-5.0.1.tgz", - "integrity": "sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ==", - "dev": true, - "dependencies": { - "camelcase": "5.0.0", - "chalk": "2.4.2", - "leven": "2.1.0", - "mri": "1.1.4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/args/node_modules/camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/args/node_modules/leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array-parallel": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz", - "integrity": "sha1-j3hTCJJu1apHjEfmTRszS2wMlH0=" - }, - "node_modules/array-series": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz", - "integrity": "sha1-3103v8XC7wdV4qpPkv6ufUtaly8=" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "engines": { - "node": "*" - } - }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", - "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "bin": { - "atob": "bin/atob.js" - }, - "engines": { - "node": ">= 4.5.0" - } - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz", - "integrity": "sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/avvio": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz", - "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==", - "dependencies": { - "archy": "^1.0.0", - "debug": "^4.0.0", - "fastq": "^1.6.1", - "queue-microtask": "^1.1.2" - } - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/axios-retry": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.1.9.tgz", - "integrity": "sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA==", - "dependencies": { - "is-retry-allowed": "^1.1.0" - } - }, - "node_modules/babel-jest": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", - "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==", - "dev": true, - "dependencies": { - "@jest/transform": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/babel__core": "^7.1.7", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.6.2", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-jest/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-jest/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/babel-jest/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/babel-jest/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz", - "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/babel-plugin-parameter-decorator": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/babel-plugin-parameter-decorator/-/babel-plugin-parameter-decorator-1.0.16.tgz", - "integrity": "sha512-yUT2WPTUg1JaPmRGRSF557m1HJ9vdFQInRWOkiOyO5a9HhqlXffJu+fQ2xd5+qU/35ICMrrk9eWKsHCairKA9w==", - "dev": true - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", - "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.13.11", - "@babel/helper-define-polyfill-provider": "^0.2.2", - "semver": "^6.1.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz", - "integrity": "sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.2", - "core-js-compat": "^3.14.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", - "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.2.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz", - "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^26.6.2", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": ">= 10.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/bcrypt": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz", - "integrity": "sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==", - "hasInstallScript": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bitsyntax": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", - "dependencies": { - "buffer-more-ints": "~1.0.0", - "debug": "~2.6.9", - "safe-buffer": "~5.1.2" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/bitsyntax/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/bitsyntax/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/bitsyntax/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, - "node_modules/block-stream2": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz", - "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", - "dependencies": { - "readable-stream": "^3.4.0" - } - }, - "node_modules/block-stream2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/block-stream2/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/boxen/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/boxen/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/boxen/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/boxen/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/boxen/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/boxen/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.16.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", - "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", - "dev": true, - "dependencies": { - "caniuse-lite": "^1.0.30001251", - "colorette": "^1.3.0", - "electron-to-chromium": "^1.3.811", - "escalade": "^3.1.1", - "node-releases": "^1.1.75" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/bson": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.5.0.tgz", - "integrity": "sha512-WoSOKryfrKx0aqhPz/DJsUlrMlOL+hkW+469Q5z5E/EQWF2xilOH7h/s5HH4j9iLRzVDwKFwVNQ3Mba16srmlw==", - "dependencies": { - "buffer": "^5.6.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/buffer-more-ints": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", - "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" - }, - "node_modules/busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "dependencies": { - "dicer": "0.3.0" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001251", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", - "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/capture-exit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", - "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", - "dev": true, - "dependencies": { - "rsvp": "^4.8.4" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/cassandra-driver": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.6.3.tgz", - "integrity": "sha512-npW670TXjTHrdb15LUFN01wssb9vvz6SuNYcppesoKcUXx3Q29nXVhRtnvsnkG0BaSnDGvCCR4udrzYLsbh+sg==", - "dependencies": { - "@types/long": "^4.0.0", - "@types/node": ">=8", - "adm-zip": "^0.5.3", - "long": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "engines": { - "node": "*" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "node_modules/cjs-module-lexer": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz", - "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==", - "dev": true - }, - "node_modules/class-transformer": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz", - "integrity": "sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA==" - }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", - "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", - "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", - "dependencies": { - "colors": "1.0.3" - }, - "engines": { - "node": ">= 0.2.0" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz", - "integrity": "sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.6.0" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colorette": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", - "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", - "dev": true - }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "node_modules/component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "node_modules/component-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-type/-/component-type-1.2.1.tgz", - "integrity": "sha1-ikeQFwAjjk/DIml3EjAibyS0Fak=" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/config": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/config/-/config-3.3.6.tgz", - "integrity": "sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg==", - "dependencies": { - "json5": "^2.1.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "dev": true, - "dependencies": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "node_modules/content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dependencies": { - "safe-buffer": "5.1.2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookiejar": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", - "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", - "dev": true - }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/core-js-compat": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.2.tgz", - "integrity": "sha512-4lUshXtBXsdmp8cDWh6KKiHUg40AjiuPD3bOWkNVsr1xkAhpUqCjaZ8lB1bKx9Gb5fXcbRbFJ4f4qpRIRTuJqQ==", - "dev": true, - "dependencies": { - "browserslist": "^4.16.7", - "semver": "7.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat/node_modules/semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "engines": { - "node": "*" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/dateformat": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", - "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, - "node_modules/decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "node_modules/deep-object-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.0.tgz", - "integrity": "sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw==" - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dependencies": { - "clone": "^1.0.2" - } - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "node_modules/denque": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", - "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "node_modules/detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "bin": { - "detect-libc": "bin/detect-libc.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "dependencies": { - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/diff-sequences": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz", - "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==", - "dev": true, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "node_modules/dynamic-dedupe": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz", - "integrity": "sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE=", - "dev": true, - "dependencies": { - "xtend": "^4.0.0" - } - }, - "node_modules/dynamic-dedupe/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "node_modules/electron-to-chromium": { - "version": "1.3.816", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.816.tgz", - "integrity": "sha512-/AvJPIJldO0NkwkfpUD7u1e4YEGRFBQpFuvl9oGCcVgWOObsZB1loxVGeVUJB9kmvfsBUUChPYdgRzx6+AKNyg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz", - "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/encoding-negotiator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz", - "integrity": "sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", - "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", - "dependencies": { - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "~7.4.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/engine.io-client": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz", - "integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==", - "dependencies": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" - } - }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/engine.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", - "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/engine.io/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.18.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz", - "integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.2", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.3", - "is-string": "^1.0.6", - "object-inspect": "^1.11.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.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", - "escape-string-regexp": "^4.0.0", - "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", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.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.merge": "^4.6.2", - "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.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz", - "integrity": "sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw==", - "dev": true, - "dependencies": { - "get-stdin": "^6.0.0" - }, - "bin": { - "eslint-config-prettier-check": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=3.14.1" - } - }, - "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", - "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", - "dev": true, - "dependencies": { - "prettier-linter-helpers": "^1.0.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": ">=5.0.0", - "prettier": ">=1.13.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/exec-sh": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", - "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", - "dev": true - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/expect": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz", - "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "ansi-styles": "^4.0.0", - "jest-get-type": "^26.3.0", - "jest-matcher-utils": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-regex-util": "^26.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/expect/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/expect/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/expect/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-json-stringify": { - "version": "2.7.8", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.8.tgz", - "integrity": "sha512-HRSGwEWe0/5EH7GEaWg1by4dInnBb1WFf4umMPr+lL5xb0VP0VbpNGklp4L0/BseD+BmtIZpjqJjnLFwaQ21dg==", - "dependencies": { - "ajv": "^6.11.0", - "deepmerge": "^4.2.2", - "rfdc": "^1.2.0", - "string-similarity": "^4.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fast-redact": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", - "integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", - "integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag==" - }, - "node_modules/fast-xml-parser": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz", - "integrity": "sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg==", - "bin": { - "xml2js": "cli.js" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - }, - "node_modules/fastfall": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", - "integrity": "sha1-P+4DMxpJ0dObPN96XpzWb0dee5Q=", - "dependencies": { - "reusify": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fastify": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.22.1.tgz", - "integrity": "sha512-TeA4+TzI7VuJrjTNqoxtSXwPEYfCwpT8j9Z3j9WrL8nrt+1bE9G0rP9hLJyvbg4it56p68YsHVhKOee69xyfmA==", - "dependencies": { - "@fastify/ajv-compiler": "^1.0.0", - "abstract-logging": "^2.0.0", - "avvio": "^7.1.2", - "fast-json-stringify": "^2.5.2", - "fastify-error": "^0.3.0", - "fastify-warning": "^0.2.0", - "find-my-way": "^4.1.0", - "flatstr": "^1.0.12", - "light-my-request": "^4.2.0", - "pino": "^6.13.0", - "proxy-addr": "^2.0.7", - "rfdc": "^1.1.4", - "secure-json-parse": "^2.0.0", - "semver": "^7.3.2", - "tiny-lru": "^7.0.0" - } - }, - "node_modules/fastify-cors": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/fastify-cors/-/fastify-cors-4.1.0.tgz", - "integrity": "sha512-Vr4AgypDkRwG16cs1ORnYItZx6FMN+gCpHvP3/nzNZL1HFzf7U/NaSgmC784VqtK8yiqSXZEoTGCsmzeSp8JVw==", - "dependencies": { - "fastify-plugin": "^2.0.0", - "vary": "^1.1.2" - } - }, - "node_modules/fastify-error": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz", - "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==" - }, - "node_modules/fastify-formbody": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-5.1.0.tgz", - "integrity": "sha512-dLFQ8gMQeLuV45J72svDbrp6CZ3hxsaiK2dd3vzoiCs9wEmCSbbJV+/afQl1cfvf19+NfCIzYVQIg1r4yO4Epw==", - "dependencies": { - "fastify-plugin": "^3.0.0" - } - }, - "node_modules/fastify-formbody/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-jwt": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/fastify-jwt/-/fastify-jwt-2.5.0.tgz", - "integrity": "sha512-QXOSfo65OxSk30TTecLh8J0LEmuQJwRPqXMDvPA9HfLdsX/xPdq/QSvQFvR5Aj1kwrFFjsyb1SNAOQmbkmpj4w==", - "dependencies": { - "@types/jsonwebtoken": "^8.5.0", - "fastify-plugin": "^3.0.0", - "http-errors": "^1.8.0", - "jsonwebtoken": "^8.5.1", - "steed": "^1.1.3" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fastify-jwt/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-multipart": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fastify-multipart/-/fastify-multipart-4.0.3.tgz", - "integrity": "sha512-RyouqARMlSgTudcPCDmxVN07YEDWojT5iQ+AkjX7DcQ+Y65hHzrOqrNveu5gs+lEIg5afGaH5ESHCNCOZYlveQ==", - "dependencies": { - "busboy": "^0.3.1", - "deepmerge": "^4.2.2", - "end-of-stream": "^1.4.4", - "fastify-error": "^0.3.0", - "fastify-plugin": "^3.0.0", - "hexoid": "^1.0.0", - "stream-wormhole": "^1.1.0" - } - }, - "node_modules/fastify-multipart/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-plugin": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-2.3.4.tgz", - "integrity": "sha512-I+Oaj6p9oiRozbam30sh39BiuiqBda7yK2nmSPVwDCfIBlKnT8YB3MY+pRQc2Fcd07bf6KPGklHJaQ2Qu81TYQ==", - "dependencies": { - "semver": "^7.3.2" - } - }, - "node_modules/fastify-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fastify-sensible": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fastify-sensible/-/fastify-sensible-3.1.1.tgz", - "integrity": "sha512-qWGsLEcc8VmLpbbWY7VJwXwWISsGBH9H4J2QeIc+l5Ov3a1lYs7ZaSnr0X8dkffdvzr9iy8wQyIuthpKTy5sZA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fastify-plugin": "^3.0.0", - "forwarded": "^0.1.2", - "http-errors": "^1.7.3", - "type-is": "^1.6.18", - "vary": "^1.1.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/fastify-sensible/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-static": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.2.3.tgz", - "integrity": "sha512-uFRgwYXZwLKyaMrByf10efO+HTjAPqyQOlUthoGljQKGCfbwUeTeE7EHadsDWeN7NMeqBE617RamVh9uqatuUw==", - "dependencies": { - "content-disposition": "^0.5.3", - "encoding-negotiator": "^2.0.1", - "fastify-plugin": "^3.0.0", - "glob": "^7.1.4", - "readable-stream": "^3.4.0", - "send": "^0.17.1" - } - }, - "node_modules/fastify-static/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-static/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastify-static/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/fastify-swagger": { - "version": "4.12.6", - "resolved": "https://registry.npmjs.org/fastify-swagger/-/fastify-swagger-4.12.6.tgz", - "integrity": "sha512-XuHyi+aPQETMsB5oOw5m8j8hror/08MSa/7Gpxon3Mu2ZtlulG8q8/XmBGB1UM0WDRifGw456IgO7kVQVPLU8A==", - "dependencies": { - "fastify-plugin": "^3.0.0", - "fastify-static": "^4.0.0", - "js-yaml": "^4.0.0", - "json-schema-resolver": "^1.3.0", - "openapi-types": "^9.1.0" - } - }, - "node_modules/fastify-swagger/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/fastify-swagger/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-swagger/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/fastify-warning": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz", - "integrity": "sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw==" - }, - "node_modules/fastify-websocket": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fastify-websocket/-/fastify-websocket-2.1.0.tgz", - "integrity": "sha512-u5zClCarOHctvzKq76Gc0rDwtWfU7pw+JGYETfSu77YzZ/uzXLDX4jB70vLliUc3nqK0zXFRDK2/KnEnfdF9Kw==", - "dependencies": { - "fastify-plugin": "^3.0.0", - "find-my-way": "^3.0.5", - "ws": "^7.4.2" - } - }, - "node_modules/fastify-websocket/node_modules/fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "node_modules/fastify-websocket/node_modules/find-my-way": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-3.0.5.tgz", - "integrity": "sha512-FweGg0cv1sBX8z7WhvBX5B5AECW4Zdh/NiB38Oa0qwSNIyPgRBCl/YjxuZn/rz38E/MMBHeVKJ22i7W3c626Gg==", - "dependencies": { - "fast-decode-uri-component": "^1.0.1", - "safe-regex2": "^2.0.0", - "semver-store": "^0.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fastify/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fastparallel": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.0.tgz", - "integrity": "sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ==", - "dependencies": { - "reusify": "^1.0.4", - "xtend": "^4.0.2" - } - }, - "node_modules/fastparallel/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/fastq": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", - "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fastseries": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz", - "integrity": "sha1-0izhO5Qz3/M4jZHb1ri9qbIaD0s=", - "dependencies": { - "reusify": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/fastseries/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-my-way": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.3.3.tgz", - "integrity": "sha512-5E4bRdaATB1MewjOCBjx4xvD205a4t2ripCnXB+YFhYEJ0NABtrcC7XLXLq0TPoFe/WYGUFqys3Qk3HCOGeNcw==", - "dependencies": { - "fast-decode-uri-component": "^1.0.1", - "fast-deep-equal": "^3.1.3", - "safe-regex2": "^2.0.0", - "semver-store": "^0.3.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatstr": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz", - "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" - }, - "node_modules/flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", - "dev": true - }, - "node_modules/follow-redirects": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", - "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" - }, - "node_modules/form-auto-content": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/form-auto-content/-/form-auto-content-2.2.0.tgz", - "integrity": "sha512-OT4qi6hNGc+fJJGieTjy+WmV1nDhg4ULATNR0Fx92YUIy9gPw8odX3z8c+IiivWITzTg8j4TcKKbsAku8l2dwQ==", - "dev": true, - "dependencies": { - "form-data": "^3.0.0" - }, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", - "dev": true, - "funding": { - "url": "https://ko-fi.com/tunnckoCore/commissions" - } - }, - "node_modules/forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "dependencies": { - "map-cache": "^0.2.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", - "dev": true - }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/generate-password": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/generate-password/-/generate-password-1.6.1.tgz", - "integrity": "sha512-JvtWSiN4KVmF6kBFi89Uz9LLN7l/EuGZYiKrIxddFlKcjSgc3D3va0Z5faooNwN85O0VBlt/ZtTdqhbQKhAOyw==" - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "engines": { - "node": "*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", - "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "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" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-dirs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", - "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", - "dev": true, - "dependencies": { - "ini": "1.3.7" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/gm": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz", - "integrity": "sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c=", - "dependencies": { - "array-parallel": "~0.1.3", - "array-series": "~0.1.5", - "cross-spawn": "^4.0.0", - "debug": "^3.1.0" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/gm/node_modules/cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "node_modules/gm/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/gm/node_modules/lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "node_modules/gm/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/gm/node_modules/yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "node_modules/growly": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", - "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", - "dev": true, - "optional": true - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", - "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dependencies": { - "isarray": "2.0.1" - } - }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "node_modules/has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hexoid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", - "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", - "engines": { - "node": ">=8" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/hpagent": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz", - "integrity": "sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ==" - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", - "dev": true - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", - "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", - "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "node_modules/is-callable": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", - "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", - "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "optional": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "dev": true, - "dependencies": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.7.tgz", - "integrity": "sha512-VxlpTBGknhQ3o7YiVjIhdLU6+oD8dPz/79vvvH4F+S/c8608UCVa9fgDpa1kZgFoUST2DCgacc70UszKgzKuvA==", - "dependencies": { - "available-typed-arrays": "^1.0.4", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "optional": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", - "dev": true - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", - "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==", - "dev": true, - "dependencies": { - "@jest/core": "^26.6.3", - "import-local": "^3.0.2", - "jest-cli": "^26.6.3" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-changed-files": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz", - "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "execa": "^4.0.0", - "throat": "^5.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-cli": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz", - "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==", - "dev": true, - "dependencies": { - "@jest/core": "^26.6.3", - "@jest/test-result": "^26.6.2", - "@jest/types": "^26.6.2", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "is-ci": "^2.0.0", - "jest-config": "^26.6.3", - "jest-util": "^26.6.2", - "jest-validate": "^26.6.2", - "prompts": "^2.0.1", - "yargs": "^15.4.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-cli/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/jest-cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-cli/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/jest-cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/jest-cli/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-cli/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-config": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz", - "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.6.3", - "@jest/types": "^26.6.2", - "babel-jest": "^26.6.3", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.6.2", - "jest-environment-node": "^26.6.2", - "jest-get-type": "^26.3.0", - "jest-jasmine2": "^26.6.3", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.2", - "jest-util": "^26.6.2", - "jest-validate": "^26.6.2", - "micromatch": "^4.0.2", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-config/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-config/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz", - "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^26.6.2", - "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-diff/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-diff/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-diff/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-diff/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-diff/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-docblock": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", - "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-each": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz", - "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "chalk": "^4.0.0", - "jest-get-type": "^26.3.0", - "jest-util": "^26.6.2", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-each/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-each/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-each/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-each/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-each/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz", - "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==", - "dev": true, - "dependencies": { - "@jest/environment": "^26.6.2", - "@jest/fake-timers": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "jest-mock": "^26.6.2", - "jest-util": "^26.6.2", - "jsdom": "^16.4.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-environment-node": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz", - "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==", - "dev": true, - "dependencies": { - "@jest/environment": "^26.6.2", - "@jest/fake-timers": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "jest-mock": "^26.6.2", - "jest-util": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-get-type": { - "version": "26.3.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", - "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", - "dev": true, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-haste-map": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", - "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^26.0.0", - "jest-serializer": "^26.6.2", - "jest-util": "^26.6.2", - "jest-worker": "^26.6.2", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7" - }, - "engines": { - "node": ">= 10.14.2" - }, - "optionalDependencies": { - "fsevents": "^2.1.2" - } - }, - "node_modules/jest-jasmine2": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz", - "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.6.2", - "@jest/source-map": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^26.6.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^26.6.2", - "jest-matcher-utils": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-runtime": "^26.6.3", - "jest-snapshot": "^26.6.2", - "jest-util": "^26.6.2", - "pretty-format": "^26.6.2", - "throat": "^5.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-jasmine2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-jasmine2/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-jasmine2/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-jasmine2/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-jasmine2/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-jasmine2/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-leak-detector": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz", - "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==", - "dev": true, - "dependencies": { - "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-matcher-utils": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz", - "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^26.6.2", - "jest-get-type": "^26.3.0", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-matcher-utils/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-matcher-utils/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-matcher-utils/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-matcher-utils/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", - "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.6.2", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "pretty-format": "^26.6.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-message-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-message-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-message-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-message-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-mock": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz", - "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/node": "*" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", - "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", - "dev": true, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-resolve": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz", - "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^26.6.2", - "read-pkg-up": "^7.0.1", - "resolve": "^1.18.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz", - "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-resolve/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-resolve/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-resolve/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-resolve/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-resolve/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz", - "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==", - "dev": true, - "dependencies": { - "@jest/console": "^26.6.2", - "@jest/environment": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.7.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-config": "^26.6.3", - "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.6.2", - "jest-leak-detector": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-resolve": "^26.6.2", - "jest-runtime": "^26.6.3", - "jest-util": "^26.6.2", - "jest-worker": "^26.6.2", - "source-map-support": "^0.5.6", - "throat": "^5.0.0" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-runner/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runner/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runner/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runner/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runner/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime": { - "version": "26.6.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz", - "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==", - "dev": true, - "dependencies": { - "@jest/console": "^26.6.2", - "@jest/environment": "^26.6.2", - "@jest/fake-timers": "^26.6.2", - "@jest/globals": "^26.6.2", - "@jest/source-map": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/transform": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0", - "cjs-module-lexer": "^0.6.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-config": "^26.6.3", - "jest-haste-map": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-mock": "^26.6.2", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.6.2", - "jest-snapshot": "^26.6.2", - "jest-util": "^26.6.2", - "jest-validate": "^26.6.2", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^15.4.1" - }, - "bin": { - "jest-runtime": "bin/jest-runtime.js" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-runtime/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/jest-runtime/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-runtime/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/jest-runtime/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "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" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-runtime/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jest-serializer": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", - "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.4" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-snapshot": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz", - "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0", - "@jest/types": "^26.6.2", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.0.0", - "chalk": "^4.0.0", - "expect": "^26.6.2", - "graceful-fs": "^4.2.4", - "jest-diff": "^26.6.2", - "jest-get-type": "^26.3.0", - "jest-haste-map": "^26.6.2", - "jest-matcher-utils": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-resolve": "^26.6.2", - "natural-compare": "^1.4.0", - "pretty-format": "^26.6.2", - "semver": "^7.3.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-snapshot/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-snapshot/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-snapshot/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", - "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-util/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-util/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-util/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-util/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz", - "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "camelcase": "^6.0.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.3.0", - "leven": "^3.1.0", - "pretty-format": "^26.6.2" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-validate/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-validate/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-validate/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-validate/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-validate/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", - "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", - "dev": true, - "dependencies": { - "@jest/test-result": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^26.6.2", - "string-length": "^4.0.1" - }, - "engines": { - "node": ">= 10.14.2" - } - }, - "node_modules/jest-watcher/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watcher/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-watcher/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/jest-watcher/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watcher/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/join-component": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz", - "integrity": "sha1-uEF7dQZho5K+4sJTfGiyqdSXfNU=" - }, - "node_modules/joycon": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz", - "integrity": "sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsdom/node_modules/acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema-resolver": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz", - "integrity": "sha512-EX7W1r8aZ/T3j8GbbBxPXi60bnsELfT90OiA1QrbGMvwzVSbyMNOAzvMFcFb8m7gKCXZLJpGe+cJOvWgoFl29A==", - "dependencies": { - "debug": "^4.1.1", - "rfdc": "^1.1.4", - "uri-js": "^4.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/json-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz", - "integrity": "sha1-GjhU4o0rvuqzHMfd9oPS3cVlJwg=" - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonfile/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/jsonwebtoken": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", - "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=4", - "npm": ">=1.4.28" - } - }, - "node_modules/jsonwebtoken/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "dev": true, - "dependencies": { - "package-json": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/light-my-request": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-4.4.4.tgz", - "integrity": "sha512-nxYLB+Lke3wGQ55HQIo/CjSS18xGyHRF0y/u7YxEwp1YsqQTxObteBXYHZY3ELSvYmqy0pRLTWbI5//zRYTXlg==", - "dependencies": { - "ajv": "^8.1.0", - "cookie": "^0.4.0", - "fastify-warning": "^0.2.0", - "readable-stream": "^3.6.0", - "set-cookie-parser": "^2.4.1" - } - }, - "node_modules/light-my-request/node_modules/ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/light-my-request/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/light-my-request/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/light-my-request/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "node_modules/lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/long": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", - "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, - "dependencies": { - "tmpl": "1.0.x" - } - }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/match-all": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz", - "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==" - }, - "node_modules/md5": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", - "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", - "dependencies": { - "charenc": "0.0.2", - "crypt": "0.0.2", - "is-buffer": "~1.1.6" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memory-pager": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", - "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", - "optional": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "dependencies": { - "mime-db": "1.49.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "node_modules/minio": { - "version": "7.0.19", - "resolved": "https://registry.npmjs.org/minio/-/minio-7.0.19.tgz", - "integrity": "sha512-DOGKauWLdmj0/y2QKXdnrhqyzRFEnUteHi6q382uujg9TjSDrA84BiQVppS2Ew6V8Rcg+2IaRkF4GR34zw9sIA==", - "dependencies": { - "async": "^3.1.0", - "block-stream2": "^2.0.0", - "es6-error": "^4.1.1", - "fast-xml-parser": "^3.17.5", - "json-stream": "^1.0.0", - "lodash": "^4.17.21", - "mime-types": "^2.1.14", - "mkdirp": "^0.5.1", - "querystring": "0.2.0", - "through2": "^3.0.1", - "web-encoding": "^1.1.5", - "xml": "^1.0.0", - "xml2js": "^0.4.15" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/minipass": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", - "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, - "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", - "engines": { - "node": "*" - } - }, - "node_modules/moment-timezone": { - "version": "0.5.33", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz", - "integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==", - "dependencies": { - "moment": ">= 2.9.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.1.0.tgz", - "integrity": "sha512-Gx9U9MsFWgJ3E0v4oHAdWvYTGBznNYPCkhmD/3i/kPTY/URnPfHD5/6VoKUFrdgQTK3icFiM9976hVbqCRBO9Q==", - "dependencies": { - "bson": "^4.4.0", - "denque": "^1.5.0", - "mongodb-connection-string-url": "^1.0.1" - }, - "engines": { - "node": ">=12.9.0" - }, - "optionalDependencies": { - "saslprep": "^1.0.0" - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-1.1.2.tgz", - "integrity": "sha512-mp5lv4guWuykOpkwNNqQ0tKKytuJUjL/aC/bu/DqoJVWL5NSh4j/u+gJ+EiOdweLujHyq6JZZqcTVipHhL5xRg==", - "dependencies": { - "@types/whatwg-url": "^8.0.0", - "whatwg-url": "^8.4.0" - } - }, - "node_modules/mri": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", - "integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/multistream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz", - "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "once": "^1.4.0", - "readable-stream": "^3.6.0" - } - }, - "node_modules/multistream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/multistream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node_modules/node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", - "dependencies": { - "semver": "^5.4.1" - } - }, - "node_modules/node-abi/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" - }, - "node_modules/node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha1-esGavSl+Caf3KnFUXZUbUX5N3iw=", - "dev": true - }, - "node_modules/node-cron": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz", - "integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==", - "dependencies": { - "moment-timezone": "^0.5.31" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node_modules/node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-notifier": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz", - "integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==", - "dev": true, - "optional": true, - "dependencies": { - "growly": "^1.3.0", - "is-wsl": "^2.2.0", - "semver": "^7.3.2", - "shellwords": "^0.1.1", - "uuid": "^8.3.0", - "which": "^2.0.2" - } - }, - "node_modules/node-notifier/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-releases": { - "version": "1.1.75", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", - "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", - "dev": true - }, - "node_modules/node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", - "deprecated": "Use uuid module instead", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/nodemon": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", - "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", - "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", - "semver": "^5.7.1", - "supports-color": "^5.5.0", - "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^4.0.0" - }, - "bin": { - "nodemon": "bin/nodemon.js" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" - } - }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/nodemon/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/notepack.io": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-2.2.0.tgz", - "integrity": "sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw==" - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", - "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/openapi-types": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.2.0.tgz", - "integrity": "sha512-3x0gg8DxhpZ5MVki7AK6jmMdVIZASmVGo9CoUtD+nksLdkqz7EzWKdfS9Oxxq1J7idnZV0b3LjqcvizfKFySpQ==" - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "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" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "dev": true, - "dependencies": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "node_modules/parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "node_modules/parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "engines": { - "node": "*" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pdf2pic": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/pdf2pic/-/pdf2pic-2.1.4.tgz", - "integrity": "sha512-8QOCvxZlYs7wsmBQbqpIApSWD/eqgXMQU+4VM0vWrXifLgXS+Ns3484sUa1Q7ddr+gwnruq/xKHzu7x1scqX6w==", - "dependencies": { - "fs-extra": "^9.1.0", - "gm": "^1.23.1" - }, - "funding": { - "type": "paypal", - "url": "https://www.paypal.me/yakovmeister" - } - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pino": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.13.1.tgz", - "integrity": "sha512-QQf67BU+cANnc/2U+wzUV20UjO5oBryWpnNyKshdLfT9BdeiXlh9wxLGmOjAuBWMYITdMs+BtJSQQNlGRNbWpA==", - "dependencies": { - "fast-redact": "^3.0.0", - "fast-safe-stringify": "^2.0.8", - "fastify-warning": "^0.2.0", - "flatstr": "^1.0.12", - "pino-std-serializers": "^3.1.0", - "quick-format-unescaped": "^4.0.3", - "sonic-boom": "^1.0.2" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-pretty": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-4.8.0.tgz", - "integrity": "sha512-mhQfHG4rw5ZFpWL44m0Utjo4GC2+HMfdNvxyA8lLw0sIqn6fCf7uQe6dPckUcW/obly+OQHD7B/MTso6LNizYw==", - "dev": true, - "dependencies": { - "@hapi/bourne": "^2.0.0", - "args": "^5.0.1", - "chalk": "^4.0.0", - "dateformat": "^4.5.1", - "fast-safe-stringify": "^2.0.7", - "jmespath": "^0.15.0", - "joycon": "^2.2.5", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "rfdc": "^1.3.0", - "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pino-pretty/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/pino-pretty/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/pino-pretty/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/pino-pretty/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pino-pretty/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/pino-pretty/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pino-std-serializers": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz", - "integrity": "sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg==" - }, - "node_modules/pino/node_modules/sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "dependencies": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - }, - "node_modules/pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "dependencies": { - "node-modules-regexp": "^1.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", - "dependencies": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.3", - "mkdirp-classic": "^0.5.3", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0" - }, - "bin": { - "prebuild-install": "bin.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/pretty-format": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", - "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", - "dev": true, - "dependencies": { - "@jest/types": "^26.6.2", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/pretty-format/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/pretty-format/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-breaker": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz", - "integrity": "sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA==" - }, - "node_modules/prompts": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", - "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/pstree.remy": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", - "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pupa": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", - "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", - "dev": true, - "dependencies": { - "escape-goat": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", - "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", - "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redis": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", - "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", - "dependencies": { - "denque": "^1.5.0", - "redis-commands": "^1.7.0", - "redis-errors": "^1.2.0", - "redis-parser": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-redis" - } - }, - "node_modules/redis-commands": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", - "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" - }, - "node_modules/redis-errors": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", - "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=", - "engines": { - "node": ">=4" - } - }, - "node_modules/redis-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", - "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", - "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/registry-auth-token": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", - "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "dev": true, - "dependencies": { - "rc": "^1.2.8" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "node_modules/regjsparser": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", - "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "node_modules/remove-trailing-slash": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz", - "integrity": "sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA==" - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ret": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", - "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rsvp": { - "version": "4.8.5", - "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", - "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", - "dev": true, - "engines": { - "node": "6.* || >= 7.*" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safe-regex/node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/safe-regex2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", - "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", - "dependencies": { - "ret": "~0.2.0" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sane": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", - "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", - "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", - "dev": true, - "dependencies": { - "@cnakazawa/watch": "^1.0.3", - "anymatch": "^2.0.0", - "capture-exit": "^2.0.0", - "exec-sh": "^0.3.2", - "execa": "^1.0.0", - "fb-watchman": "^2.0.0", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5" - }, - "bin": { - "sane": "src/cli.js" - }, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/sane/node_modules/anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "dependencies": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "node_modules/sane/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/braces/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/sane/node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sane/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "dependencies": { - "remove-trailing-separator": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/sane/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/sane/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sane/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/saslprep": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", - "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/secure-json-parse": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", - "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==" - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "dev": true, - "dependencies": { - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semver-store": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", - "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" - }, - "node_modules/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dependencies": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/send/node_modules/http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - }, - "node_modules/send/node_modules/setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "node_modules/set-cookie-parser": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", - "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==" - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/sharp": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.29.1.tgz", - "integrity": "sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ==", - "hasInstallScript": true, - "dependencies": { - "color": "^4.0.1", - "detect-libc": "^1.0.3", - "node-addon-api": "^4.1.0", - "prebuild-install": "^6.1.4", - "semver": "^7.3.5", - "simple-get": "^3.1.0", - "tar-fs": "^2.1.1", - "tunnel-agent": "^0.6.0" - }, - "engines": { - "node": ">=12.13.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/sharp/node_modules/node-addon-api": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.2.0.tgz", - "integrity": "sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q==" - }, - "node_modules/sharp/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/shellwords": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", - "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", - "dev": true, - "optional": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "node_modules/simple-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", - "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "dependencies": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "node_modules/simple-get/node_modules/decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "dependencies": { - "mimic-response": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/simple-get/node_modules/mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/socket.io": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", - "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", - "dependencies": { - "debug": "~4.1.0", - "engine.io": "~3.5.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.4.0", - "socket.io-parser": "~3.4.0" - } - }, - "node_modules/socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" - }, - "node_modules/socket.io-client": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", - "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", - "dependencies": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.5.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - } - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/socket.io-client/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "node_modules/socket.io-client/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "node_modules/socket.io-client/node_modules/socket.io-parser": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", - "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", - "dependencies": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - }, - "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "dev": true, - "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-redis": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/socket.io-redis/-/socket.io-redis-5.4.0.tgz", - "integrity": "sha512-yCQm/Sywd3d08WXUfZRxt6O+JV2vWoPgWK6GVjiM0GkBtq5cpLOk8oILRPKbzTv1VEtSYmK41q0xzcgDinMbmQ==", - "dependencies": { - "debug": "~4.1.0", - "notepack.io": "~2.2.0", - "redis": "^3.0.0", - "socket.io-adapter": "~1.1.0", - "uid2": "0.0.3" - } - }, - "node_modules/socket.io-redis/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/socket.io/node_modules/component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/socket.io/node_modules/isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "node_modules/socket.io/node_modules/socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", - "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", - "dependencies": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - } - }, - "node_modules/socketio-jwt": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/socketio-jwt/-/socketio-jwt-4.6.2.tgz", - "integrity": "sha512-bcCnit/cCvqtC921Gwuqor+LpLKrpREmPACVgLfdbFBL95w2nPF7lOxsOxyeRrhc5Kot/1jUSW5+kLo23zJIMA==", - "dependencies": { - "jsonwebtoken": "^8.3.0", - "xtend": "~2.1.2" - } - }, - "node_modules/sonic-boom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.1.0.tgz", - "integrity": "sha512-x2j9LXx27EDlyZEC32gBM+scNVMdPutU7FIKV2BOTKCnPrp7bY5BsplCMQ4shYYR3IhDSIrEXoqb6GlS+z7KyQ==", - "dev": true, - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", - "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", - "optional": true, - "dependencies": { - "memory-pager": "^1.0.2" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/split2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/split2/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/steed": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz", - "integrity": "sha1-8VJd1a2xLrIb90dJU3Zo1iW5q8U=", - "dependencies": { - "fastfall": "^1.5.0", - "fastparallel": "^2.2.0", - "fastq": "^1.3.0", - "fastseries": "^1.7.0", - "reusify": "^1.0.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "node_modules/stream-wormhole": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", - "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, - "node_modules/string-argv": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz", - "integrity": "sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-similarity": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz", - "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==" - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/superagent": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz", - "integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==", - "dev": true, - "dependencies": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.2.0", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.3.5" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/superagent/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/superagent/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/superagent/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/superagent/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "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" - } - }, - "node_modules/superagent/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/superagent/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/supertest": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", - "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", - "dev": true, - "dependencies": { - "methods": "^1.1.2", - "superagent": "^3.8.3" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/table": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", - "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, - "dependencies": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.6.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", - "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/table/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar": { - "version": "6.1.10", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.10.tgz", - "integrity": "sha512-kvvfiVvjGMxeUNB6MyYv5z7vhfFRwbwCXJAeL0/lnbrttBVqcMOnpHUf0X42LrPMR8mMpgapkJMchFH4FSHzNA==", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-fs/node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/tar-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/term-size": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", - "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/throat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", - "dev": true - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "node_modules/through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/tiny-lru": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz", - "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==", - "engines": { - "node": ">=6" - } - }, - "node_modules/tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", - "dev": true - }, - "node_modules/to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", - "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, - "bin": { - "nodetouch": "bin/nodetouch.js" - } - }, - "node_modules/touch/node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - } - }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/ts-jest": { - "version": "26.5.6", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz", - "integrity": "sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA==", - "dev": true, - "dependencies": { - "bs-logger": "0.x", - "buffer-from": "1.x", - "fast-json-stable-stringify": "2.x", - "jest-util": "^26.1.0", - "json5": "2.x", - "lodash": "4.x", - "make-error": "1.x", - "mkdirp": "1.x", - "semver": "7.x", - "yargs-parser": "20.x" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": ">= 10" - }, - "peerDependencies": { - "jest": ">=26 <27", - "typescript": ">=3.8 <5.0" - } - }, - "node_modules/ts-jest/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-jest/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" - } - }, - "node_modules/ts-node-dev": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz", - "integrity": "sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.1", - "dynamic-dedupe": "^0.3.0", - "minimist": "^1.2.5", - "mkdirp": "^1.0.4", - "resolve": "^1.0.0", - "rimraf": "^2.6.1", - "source-map-support": "^0.5.12", - "tree-kill": "^1.2.2", - "ts-node": "^9.0.0", - "tsconfig": "^7.0.0" - }, - "bin": { - "ts-node-dev": "lib/bin.js", - "tsnd": "lib/bin.js" - }, - "engines": { - "node": ">=0.8.0" - }, - "peerDependencies": { - "node-notifier": "*", - "typescript": "*" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/ts-node-dev/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ts-node-dev/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/tsc-watch": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.5.0.tgz", - "integrity": "sha512-aXhN4jY+1YEcn/NwCQ/+fHqU43EqOpW+pS+933EPsVEsrKhvyrodPDIjQsk1a1niFrabAK3RIBrRbAslVefEbQ==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "node-cleanup": "^2.1.2", - "ps-tree": "^1.2.0", - "string-argv": "^0.1.1", - "strip-ansi": "^6.0.0" - }, - "bin": { - "tsc-watch": "index.js" - }, - "engines": { - "node": ">=8.17.0" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uid2": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", - "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" - }, - "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", - "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "dev": true, - "dependencies": { - "debug": "^2.2.0" - } - }, - "node_modules/undefsafe/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/undefsafe/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/union-value/node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unoconv-promise": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/unoconv-promise/-/unoconv-promise-1.0.8.tgz", - "integrity": "sha512-YBVskYpnYj5KQS5aCnE+a+n7jFOmL9dOKzfymw5mKsZhO2K6LrBLAGzReXpOU3x77tTEeJzZYTgrhqIbtF9Acw==", - "dependencies": { - "chai": "^4.2.0", - "debug": "^4.1.1", - "mime": "^2.4.0" - } - }, - "node_modules/unoconv-promise/node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/update-notifier": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", - "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", - "dev": true, - "dependencies": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/yeoman/update-notifier?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/update-notifier/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/update-notifier/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/update-notifier/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-notifier/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/util": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", - "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/uuid-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uuid-time/-/uuid-time-1.0.0.tgz", - "integrity": "sha1-i7GPpwiZh+8lsMQEcZATPPo6FMY=" - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8-to-istanbul": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz", - "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dev": true, - "dependencies": { - "makeerror": "1.0.x" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/web-encoding": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz", - "integrity": "sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==", - "dependencies": { - "util": "^0.12.3" - }, - "optionalDependencies": { - "@zxing/text-encoding": "0.9.0" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.6.tgz", - "integrity": "sha512-DdY984dGD5sQ7Tf+x1CkXzdg85b9uEel6nr4UkFg1LoE9OXv3uRuZhe5CoWdawhGACeFpEZXH8fFLQnDhbpm/Q==", - "dependencies": { - "available-typed-arrays": "^1.0.4", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/widest-line/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/widest-line/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=" - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", - "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, - "node_modules/xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/xtend/node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "dev": true - }, - "@babel/core": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", - "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.15.0", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", - "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", - "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz", - "integrity": "sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-split-export-declaration": "^7.14.5" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", - "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "regexpu-core": "^4.7.1" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", - "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.13.0", - "@babel/helper-module-imports": "^7.12.13", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/traverse": "^7.13.0", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", - "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", - "dev": true, - "requires": { - "@babel/types": "^7.15.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", - "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-wrap-function": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", - "dev": true, - "requires": { - "@babel/types": "^7.14.8" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", - "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.5" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", - "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" - } - }, - "@babel/helpers": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", - "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", - "dev": true, - "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - } - }, - "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", - "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", - "dev": true - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz", - "integrity": "sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", - "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", - "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-decorators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz", - "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-decorators": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", - "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", - "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", - "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", - "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", - "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", - "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", - "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.14.7", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.14.5" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", - "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", - "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", - "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-create-class-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", - "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-decorators": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz", - "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", - "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", - "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-remap-async-to-generator": "^7.14.5" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", - "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.15.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz", - "integrity": "sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz", - "integrity": "sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.14.5", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", - "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", - "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", - "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", - "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", - "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", - "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", - "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", - "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", - "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", - "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz", - "integrity": "sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-simple-access": "^7.14.8", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", - "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.5", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", - "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz", - "integrity": "sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", - "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", - "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", - "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", - "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", - "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", - "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", - "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.14.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", - "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", - "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", - "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", - "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz", - "integrity": "sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/plugin-syntax-typescript": "^7.14.5" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", - "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", - "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.14.5", - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/preset-env": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz", - "integrity": "sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-plugin-utils": "^7.14.5", - "@babel/helper-validator-option": "^7.14.5", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.9", - "@babel/plugin-proposal-class-properties": "^7.14.5", - "@babel/plugin-proposal-class-static-block": "^7.14.5", - "@babel/plugin-proposal-dynamic-import": "^7.14.5", - "@babel/plugin-proposal-export-namespace-from": "^7.14.5", - "@babel/plugin-proposal-json-strings": "^7.14.5", - "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", - "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.14.7", - "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", - "@babel/plugin-proposal-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-private-methods": "^7.14.5", - "@babel/plugin-proposal-private-property-in-object": "^7.14.5", - "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.14.5", - "@babel/plugin-transform-async-to-generator": "^7.14.5", - "@babel/plugin-transform-block-scoped-functions": "^7.14.5", - "@babel/plugin-transform-block-scoping": "^7.14.5", - "@babel/plugin-transform-classes": "^7.14.9", - "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.7", - "@babel/plugin-transform-dotall-regex": "^7.14.5", - "@babel/plugin-transform-duplicate-keys": "^7.14.5", - "@babel/plugin-transform-exponentiation-operator": "^7.14.5", - "@babel/plugin-transform-for-of": "^7.14.5", - "@babel/plugin-transform-function-name": "^7.14.5", - "@babel/plugin-transform-literals": "^7.14.5", - "@babel/plugin-transform-member-expression-literals": "^7.14.5", - "@babel/plugin-transform-modules-amd": "^7.14.5", - "@babel/plugin-transform-modules-commonjs": "^7.15.0", - "@babel/plugin-transform-modules-systemjs": "^7.14.5", - "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.9", - "@babel/plugin-transform-new-target": "^7.14.5", - "@babel/plugin-transform-object-super": "^7.14.5", - "@babel/plugin-transform-parameters": "^7.14.5", - "@babel/plugin-transform-property-literals": "^7.14.5", - "@babel/plugin-transform-regenerator": "^7.14.5", - "@babel/plugin-transform-reserved-words": "^7.14.5", - "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.14.6", - "@babel/plugin-transform-sticky-regex": "^7.14.5", - "@babel/plugin-transform-template-literals": "^7.14.5", - "@babel/plugin-transform-typeof-symbol": "^7.14.5", - "@babel/plugin-transform-unicode-escapes": "^7.14.5", - "@babel/plugin-transform-unicode-regex": "^7.14.5", - "@babel/preset-modules": "^0.1.4", - "@babel/types": "^7.15.0", - "babel-plugin-polyfill-corejs2": "^0.2.2", - "babel-plugin-polyfill-corejs3": "^0.2.2", - "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.16.0", - "semver": "^6.3.0" + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "@babel/preset-modules": { @@ -17425,31 +1272,155 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { - "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true + "globals": { + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@fastify/ajv-compiler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz", + "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==", + "requires": { + "ajv": "^6.12.6" + } + }, + "@fastify/busboy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.0.0.tgz", + "integrity": "sha512-tzTXX1TFEjWCseEsNdIlXXkD+48uJoN+zpqIojUX4pSoMscsbhO/UuVEB5SzJucexqDWOo2ma0ECwdD7hZdrzg==", + "requires": { + "text-decoding": "^1.0.0" + } + }, + "@fastify/caching": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@fastify/caching/-/caching-7.0.0.tgz", + "integrity": "sha512-zMZzUmtByWKeqW8WMt0PILgGIUHLopSGjVPK2pDSPhcrdf9/B/gA4FiW4ylJVY0fhkW18awqI3z+tgUiY6mPsw==", + "requires": { + "abstract-cache": "^1.0.1", + "fastify-plugin": "^3.0.1", + "uid-safe": "^2.1.5" + }, + "dependencies": { + "fastify-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz", + "integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==" + } + } + }, + "@fastify/formbody": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-6.0.0.tgz", + "integrity": "sha512-YzPTXJbB3CzDMqU5K9YGSBt/nc/RDFZSxSWZ4SoqA3T2VRJzCPd7sZFpggdmlBRWhEBlvl0EWW7EX33kfbbFlg==", + "requires": { + "fastify-plugin": "^3.0.0" + }, + "dependencies": { + "fastify-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz", + "integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==" + } + } + }, + "@fastify/static": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@fastify/static/-/static-5.0.1.tgz", + "integrity": "sha512-0lReUKWVOt2i5i1KoBLYsbcMBthq5eiEoUQrFceoXJkCv+OyA0iLl6hGxcmnMRxLsl/Netrzt1NNOpg4muCcuw==", + "requires": { + "content-disposition": "^0.5.3", + "encoding-negotiator": "^2.0.1", + "fastify-plugin": "^3.0.0", + "glob": "^7.1.4", + "p-limit": "^3.1.0", + "readable-stream": "^3.4.0", + "send": "^0.17.1" + }, + "dependencies": { + "fastify-plugin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz", + "integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==" } } }, - "@fastify/ajv-compiler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz", - "integrity": "sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg==", + "@ffprobe-installer/darwin-arm64": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/darwin-arm64/-/darwin-arm64-5.0.1.tgz", + "integrity": "sha512-vwNCNjokH8hfkbl6m95zICHwkSzhEvDC3GVBcUp5HX8+4wsX10SP3B+bGur7XUzTIZ4cQpgJmEIAx6TUwRepMg==", + "optional": true + }, + "@ffprobe-installer/darwin-x64": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/darwin-x64/-/darwin-x64-5.0.0.tgz", + "integrity": "sha512-Zl0UkZ+wW/eyMKBPLTUCcNQch2VDnZz/cBn1DXv3YtCBVbYd9aYzGj4MImdxgWcoE0+GpbfbO6mKGwMq5HCm6A==", + "optional": true + }, + "@ffprobe-installer/ffprobe": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/ffprobe/-/ffprobe-1.4.1.tgz", + "integrity": "sha512-3WJvxU0f4d7IOZdzoVCAj9fYtiQNC6E0521FJFe9iP5Ej8auTXU7TsrUzIAG1CydeQI+BnM3vGog92SCcF9KtA==", "requires": { - "ajv": "^6.12.6" + "@ffprobe-installer/darwin-arm64": "5.0.1", + "@ffprobe-installer/darwin-x64": "5.0.0", + "@ffprobe-installer/linux-arm": "5.0.0", + "@ffprobe-installer/linux-arm64": "5.0.0", + "@ffprobe-installer/linux-ia32": "5.0.0", + "@ffprobe-installer/linux-x64": "5.0.0", + "@ffprobe-installer/win32-ia32": "5.0.0", + "@ffprobe-installer/win32-x64": "5.0.0" } }, + "@ffprobe-installer/linux-arm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-arm/-/linux-arm-5.0.0.tgz", + "integrity": "sha512-mM1PPxP2UX5SUvhy0urcj5U8UolwbYgmnXA/eBWbW78k6N2Wk1COvcHYzOPs6c5yXXL6oshS2rZHU1kowigw7g==", + "optional": true + }, + "@ffprobe-installer/linux-arm64": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-arm64/-/linux-arm64-5.0.0.tgz", + "integrity": "sha512-IwFbzhe1UydR849YXLPP0RMpHgHXSuPO1kznaCHcU5FscFBV5gOZLkdD8e/xrcC8g/nhKqy0xMjn5kv6KkFQlQ==", + "optional": true + }, + "@ffprobe-installer/linux-ia32": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-ia32/-/linux-ia32-5.0.0.tgz", + "integrity": "sha512-c3bWlWEDMST59SAZycVh0oyc2eNS/CxxeRjoNryGRgqcZX3EJWJJQL1rAXbpQOMLMi8to1RqnmMuwPJgLLjjUA==", + "optional": true + }, + "@ffprobe-installer/linux-x64": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/linux-x64/-/linux-x64-5.0.0.tgz", + "integrity": "sha512-zgLnWJFvMGCaw1txGtz84sMEQt6mQUzdw86ih9S/kZOWnp06Gj/ams/EXxEkAxgAACCVM6/O0mkDe/6biY5tgA==", + "optional": true + }, + "@ffprobe-installer/win32-ia32": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/win32-ia32/-/win32-ia32-5.0.0.tgz", + "integrity": "sha512-NnDdAZD6ShFXzJeCkAFl2ZjAv7GcJWYudLA+0T/vjZwvskBop+sq1PGfdmVltfFDcdQiomoThRhn9Xiy9ZC71g==", + "optional": true + }, + "@ffprobe-installer/win32-x64": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@ffprobe-installer/win32-x64/-/win32-x64-5.0.0.tgz", + "integrity": "sha512-P4ZMRFxVMnfMsOyTfBM/+nkTodLeOUfXNPo+X1bKEWBiZxRErqX/IHS5sLA0yAH8XmtKZcL7Cu6M26ztGcQYxw==", + "optional": true + }, "@hapi/bourne": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz", @@ -17504,57 +1475,6 @@ "jest-message-util": "^26.6.2", "jest-util": "^26.6.2", "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "@jest/core": { @@ -17591,57 +1511,6 @@ "rimraf": "^3.0.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "@jest/environment": { @@ -17712,63 +1581,6 @@ "string-length": "^4.0.1", "terminal-link": "^2.0.0", "v8-to-istanbul": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "@jest/source-map": { @@ -17780,14 +1592,6 @@ "callsites": "^3.0.0", "graceful-fs": "^4.2.4", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "@jest/test-result": { @@ -17833,130 +1637,22 @@ "jest-util": "^26.6.2", "micromatch": "^4.0.2", "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/types": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", - "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" } }, "@mapbox/node-pre-gyp": { @@ -17975,13 +1671,10 @@ "tar": "^6.1.0" }, "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" } } }, @@ -18020,48 +1713,67 @@ "join-component": "^1.1.0" } }, + "@selderee/plugin-htmlparser2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", + "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", + "requires": { + "domhandler": "^4.2.0", + "selderee": "^0.6.0" + }, + "dependencies": { + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + } + } + }, "@sentry/core": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.13.3.tgz", - "integrity": "sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA==", - "requires": { - "@sentry/hub": "6.13.3", - "@sentry/minimal": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-6.17.2.tgz", + "integrity": "sha512-Uew0CNMr+QvowrF4EJYjOUgHep/sZJ3l5zevPEELugIgqWBodd+ZDCV3fQFR7cr6KOqx1rMgVrgcKIkLl0l+RA==", + "requires": { + "@sentry/hub": "6.17.2", + "@sentry/minimal": "6.17.2", + "@sentry/types": "6.17.2", + "@sentry/utils": "6.17.2", "tslib": "^1.9.3" } }, "@sentry/hub": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.3.tgz", - "integrity": "sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw==", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.17.2.tgz", + "integrity": "sha512-CMi6jU920bTwRTmGHjP4u8toOx4gm1dsx+rsxvp+FKzqRwpwoyi9mOw8oEYERVzaqaYceGdFylyRUrjdf0f77g==", "requires": { - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", + "@sentry/types": "6.17.2", + "@sentry/utils": "6.17.2", "tslib": "^1.9.3" } }, "@sentry/minimal": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.3.tgz", - "integrity": "sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw==", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.17.2.tgz", + "integrity": "sha512-Cdh+iM6QhLKfxwUWWP4mk2K7+EsQj4tuF2dGQke4Zcbp7zQ7wbcMruUcZHiZfvg5kiSYxwNVkH7cXMzcO7AJsg==", "requires": { - "@sentry/hub": "6.13.3", - "@sentry/types": "6.13.3", + "@sentry/hub": "6.17.2", + "@sentry/types": "6.17.2", "tslib": "^1.9.3" } }, "@sentry/node": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.13.3.tgz", - "integrity": "sha512-ZeZSw+TcPcf4e0j7iEqNMtoVmz+WFW/TEoGokXIwysZqSgchKdAXDHqn+CqUqFan7d76JcJmzztAUK2JruQ2Kg==", - "requires": { - "@sentry/core": "6.13.3", - "@sentry/hub": "6.13.3", - "@sentry/tracing": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-6.17.2.tgz", + "integrity": "sha512-358z45WaejnsE8RZVpuLJJiFVCSEi0TRY7P60CljZuz8rnvniD3G0tuXChvu4djVty8NScWZHT/QoxvuJdTHgQ==", + "requires": { + "@sentry/core": "6.17.2", + "@sentry/hub": "6.17.2", + "@sentry/tracing": "6.17.2", + "@sentry/types": "6.17.2", + "@sentry/utils": "6.17.2", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -18069,28 +1781,28 @@ } }, "@sentry/tracing": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.3.tgz", - "integrity": "sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q==", - "requires": { - "@sentry/hub": "6.13.3", - "@sentry/minimal": "6.13.3", - "@sentry/types": "6.13.3", - "@sentry/utils": "6.13.3", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.17.2.tgz", + "integrity": "sha512-oWY2Ga+5D5f90utvfF2Y0eQvme+eS768ZWjR+klRYgZWoY8r1v8uWwWsvroYU1g+h6X0G/xh3giFjsdOWtRENw==", + "requires": { + "@sentry/hub": "6.17.2", + "@sentry/minimal": "6.17.2", + "@sentry/types": "6.17.2", + "@sentry/utils": "6.17.2", "tslib": "^1.9.3" } }, "@sentry/types": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.13.3.tgz", - "integrity": "sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A==" + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-6.17.2.tgz", + "integrity": "sha512-UrFLRDz5mn253O8k/XftLxoldF+NyZdkqKLGIQmST5HEVr7ub9nQJ4Y5ZFA3zJYWpraaW8faIbuw+pgetC8hmQ==" }, "@sentry/utils": { - "version": "6.13.3", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.3.tgz", - "integrity": "sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag==", + "version": "6.17.2", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-6.17.2.tgz", + "integrity": "sha512-ePWtO44KJQwUULOiU86fa1WU3Ird2TH0i39gqB2d3zNS3QyVp9qPlzSdPKSPJ9LdgadzBHw7ikEuE+GY8JTrhA==", "requires": { - "@sentry/types": "6.13.3", + "@sentry/types": "6.17.2", "tslib": "^1.9.3" } }, @@ -18118,6 +1830,22 @@ "@sinonjs/commons": "^1.7.0" } }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==" + }, + "@socket.io/redis-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-7.1.0.tgz", + "integrity": "sha512-vbsNJKUQgtVHcOqNL2ac8kSemTVNKHRzYPldqQJt0eFKvlAtAviuAMzBP0WmOp5OoRLQMjhVsVvgMzzMsVsK5g==", + "requires": { + "debug": "~4.3.1", + "notepack.io": "~2.2.0", + "socket.io-adapter": "~2.3.0", + "uid2": "0.0.3" + } + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -18236,10 +1964,9 @@ "dev": true }, "@types/component-emitter": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", - "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==", - "dev": true + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" }, "@types/config": { "version": "0.0.36", @@ -18247,20 +1974,21 @@ "integrity": "sha512-EoAeT1MyFWh2BJvBDEFInY714bQBbHOAucqxqqhprhbBFqr+B7fuN5T9CJqUIGDzvwubnKKRqmSo6yPo0aSpNw==", "dev": true }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, "@types/cookiejar": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", "dev": true }, - "@types/engine.io": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.7.tgz", - "integrity": "sha512-qNjVXcrp+1sS8YpRUa714r0pgzOwESdW5UjHL7D/2ZFdBX0BXUXtg1LUrp+ylvqbvMcMWUy73YpRoxPN2VoKAQ==", - "dev": true, - "requires": { - "@types/node": "*" - } + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "@types/eslint": { "version": "7.28.0", @@ -18287,6 +2015,24 @@ "fastify-multipart": "*" } }, + "@types/fastify-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@types/fastify-static/-/fastify-static-2.2.1.tgz", + "integrity": "sha512-jDE4J3nkhmBbDwopkaEmJzbGnCc1YWlkCeKPtdh9B6SuPH3RJv8SMf1Tv3nGel/RL2GUWN3tkhhFVJogqrmtMw==", + "dev": true, + "requires": { + "fastify-static": "*" + } + }, + "@types/fluent-ffmpeg": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.20.tgz", + "integrity": "sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -18296,6 +2042,12 @@ "@types/node": "*" } }, + "@types/html-to-text": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@types/html-to-text/-/html-to-text-8.1.1.tgz", + "integrity": "sha512-QFcqfc7TiVbvIX8Fc2kWUxakruI1Ay6uitaGCYHzI5M0WHQROV5D2XeSaVrK0FmvssivXum4yERVnJsiuH61Ww==", + "dev": true + }, "@types/istanbul-lib-coverage": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", @@ -18373,6 +2125,15 @@ "mongodb": "*" } }, + "@types/needle": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@types/needle/-/needle-2.5.3.tgz", + "integrity": "sha512-RwgTwMRaedfyCBe5SSWMpm1Yqzc5UPZEMw0eAd09OSyV93nLRj9/evMGZmgFeHKzUOd4xxtHvgtc+rjcBjI1Qg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "14.17.11", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.11.tgz", @@ -18425,6 +2186,17 @@ "@types/pino-pretty": "*", "@types/pino-std-serializers": "*", "sonic-boom": "^2.1.0" + }, + "dependencies": { + "sonic-boom": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.1.0.tgz", + "integrity": "sha512-x2j9LXx27EDlyZEC32gBM+scNVMdPutU7FIKV2BOTKCnPrp7bY5BsplCMQ4shYYR3IhDSIrEXoqb6GlS+z7KyQ==", + "dev": true, + "requires": { + "atomic-sleep": "^1.0.0" + } + } } }, "@types/pino-pretty": { @@ -18451,33 +2223,45 @@ "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, - "@types/redis": { - "version": "2.8.31", - "resolved": "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz", - "integrity": "sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA==", + "@types/probe-image-size": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.0.tgz", + "integrity": "sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew==", "dev": true, "requires": { + "@types/needle": "*", "@types/node": "*" } }, - "@types/sharp": { - "version": "0.28.6", - "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.28.6.tgz", - "integrity": "sha512-AjKjo5vk5mkcTrWL0U1zFUdCp/uqLebvbe7ezAJx0tgp6ST9JmfsYK1q1lpjfPM5S1YQ1wr5uboPSu2S8UO9yw==", + "@types/pump": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/pump/-/pump-1.1.1.tgz", + "integrity": "sha512-wpRerjHDxFBQ4r8XNv3xHJZeuqrBBoeQ/fhgkooV2F7KsPIYRROb/+f9ODgZfOEyO5/w2ej4YQdpPPXipT8DAA==", "dev": true, "requires": { "@types/node": "*" } }, - "@types/socket.io": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz", - "integrity": "sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg==", - "dev": true, + "@types/random-useragent": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@types/random-useragent/-/random-useragent-0.3.1.tgz", + "integrity": "sha512-yVz7897JjjwS6V+lmxlu8pktzNnNWgtF9MGxfaRfI8o+hQageO9K+0hfwr8PspdFJIIRE9KkLqp4o5tlQqv/0w==", + "dev": true + }, + "@types/redis": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/@types/redis/-/redis-4.0.11.tgz", + "integrity": "sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg==", "requires": { - "@types/engine.io": "*", - "@types/node": "*", - "@types/socket.io-parser": "*" + "redis": "*" + } + }, + "@types/sharp": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.29.5.tgz", + "integrity": "sha512-3TC+S3H5RwnJmLYMHrcdfNjz/CaApKmujjY9b6PU/pE6n0qfooi99YqXGWoW8frU9EWYj/XTI35Pzxa+ThAZ5Q==", + "requires": { + "@types/node": "*" } }, "@types/socket.io-client": { @@ -18490,21 +2274,10 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz", "integrity": "sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew==", - "dev": true, "requires": { "socket.io-parser": "*" } }, - "@types/socket.io-redis": { - "version": "1.0.27", - "resolved": "https://registry.npmjs.org/@types/socket.io-redis/-/socket.io-redis-1.0.27.tgz", - "integrity": "sha512-oyJPDjn5Dnci3wZD2bd1jfPsJkqvTwoNGpOIF+/+P45cOn4zrYsUO9mcGN/shoxIlCz6bcdRhSRXWwZFGQc1PA==", - "dev": true, - "requires": { - "@types/redis": "*", - "@types/socket.io": "*" - } - }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -18599,17 +2372,6 @@ "regexpp": "^3.1.0", "semver": "^7.3.5", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "@typescript-eslint/experimental-utils": { @@ -18624,6 +2386,17 @@ "@typescript-eslint/typescript-estree": "4.29.3", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + } } }, "@typescript-eslint/parser": { @@ -18667,17 +2440,6 @@ "is-glob": "^4.0.1", "semver": "^7.3.5", "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "@typescript-eslint/visitor-keys": { @@ -18707,6 +2469,16 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "abstract-cache": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/abstract-cache/-/abstract-cache-1.0.1.tgz", + "integrity": "sha512-EfUeMhRUbG5bVVbrSY/ogLlFXoyfMAPxMlSP7wrEqH53d+59r2foVy9a5KjmprLKFLOfPQCNKEfpBN/nQ76chw==", + "requires": { + "clone": "^2.1.1", + "lru_map": "^0.3.3", + "merge-options": "^1.0.0" + } + }, "abstract-logging": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", @@ -18741,8 +2513,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -18788,9 +2559,9 @@ } }, "amqplib": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.7.1.tgz", - "integrity": "sha512-KePK3tTOLGU4emTo+PwSDMbc123jrxo13FpRpim1LzJoSlQrIBB2/kMeCC40jK/Zb0olHGaABjLqXDsdK46iLA==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz", + "integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==", "requires": { "bitsyntax": "~0.1.0", "bluebird": "^3.7.2", @@ -18798,6 +2569,29 @@ "readable-stream": "1.x >=1.1.9", "safe-buffer": "~5.2.1", "url-parse": "~1.5.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } } }, "analytics-node": { @@ -18816,44 +2610,23 @@ } }, "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", "dev": true, "requires": { - "string-width": "^3.0.0" + "string-width": "^4.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" } } } @@ -18871,20 +2644,27 @@ "dev": true, "requires": { "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "anymatch": { @@ -18916,11 +2696,6 @@ "readable-stream": "^2.0.6" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -18977,17 +2752,61 @@ "mri": "1.1.4" }, "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, "camelcase": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -19054,9 +2873,9 @@ "dev": true }, "async": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz", - "integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==" + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" }, "asynckit": { "version": "0.4.0", @@ -19126,57 +2945,6 @@ "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "babel-plugin-dynamic-import-node": { @@ -19228,6 +2996,14 @@ "@babel/compat-data": "^7.13.11", "@babel/helper-define-polyfill-provider": "^0.2.2", "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "babel-plugin-polyfill-corejs3": { @@ -19383,26 +3159,6 @@ "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } } }, "blob": { @@ -19416,26 +3172,6 @@ "integrity": "sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==", "requires": { "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } } }, "bluebird": { @@ -19443,6 +3179,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, "boxen": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", @@ -19459,15 +3200,6 @@ "widest-line": "^3.1.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -19478,64 +3210,16 @@ "supports-color": "^7.1.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" + "strip-ansi": "^6.0.1" } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true } } }, @@ -19627,14 +3311,6 @@ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, - "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "requires": { - "dicer": "0.3.0" - } - }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -19667,6 +3343,15 @@ "responselike": "^1.0.2" }, "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -19697,9 +3382,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001251", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", - "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==", "dev": true }, "capture-exit": { @@ -19736,14 +3421,12 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "char-regex": { @@ -19762,6 +3445,43 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, + "cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "requires": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "dependencies": { + "parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "requires": { + "entities": "^4.3.0" + } + } + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + } + }, "chokidar": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", @@ -19779,9 +3499,9 @@ } }, "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "ci-info": { "version": "2.0.0", @@ -19810,74 +3530,6 @@ "define-property": "^0.2.5", "isobject": "^3.0.0", "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } } }, "cli-boxes": { @@ -19915,34 +3567,12 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - } } }, "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "clone-response": { "version": "1.0.2", @@ -19981,22 +3611,22 @@ } }, "color": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz", - "integrity": "sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", "requires": { "color-convert": "^2.0.1", - "color-string": "^1.6.0" + "color-string": "^1.9.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" }, "dependencies": { - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", @@ -20004,24 +3634,15 @@ } } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "color-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", - "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "requires": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" @@ -20047,6 +3668,11 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -20171,6 +3797,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -20186,6 +3821,23 @@ "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "crypt": { @@ -20199,6 +3851,23 @@ "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", "dev": true }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -20273,12 +3942,18 @@ "dev": true }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "requires": { - "mimic-response": "^1.0.0" + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + } } }, "deep-eql": { @@ -20316,6 +3991,13 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "requires": { "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + } } }, "defer-to-connect": { @@ -20333,13 +4015,71 @@ } }, "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "^0.1.0" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "delayed-stream": { @@ -20369,9 +4109,9 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" }, "detect-newline": { "version": "3.1.0", @@ -20379,14 +4119,6 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "requires": { - "streamsearch": "0.1.2" - } - }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -20408,6 +4140,11 @@ "path-type": "^4.0.0" } }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -20417,6 +4154,21 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, "domexception": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", @@ -20434,6 +4186,24 @@ } } }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -20462,14 +4232,6 @@ "dev": true, "requires": { "xtend": "^4.0.0" - }, - "dependencies": { - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - } } }, "ecdsa-sig-formatter": { @@ -20497,11 +4259,25 @@ "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==", "dev": true }, + "emoji-name-map": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/emoji-name-map/-/emoji-name-map-1.2.9.tgz", + "integrity": "sha512-MSM8y6koSqh/2uEMI2VoKA+Ac0qL5RkgFGP/pzL6n5FOrOJ7FOZFxgs7+uNpqA+AT+WmdbMPXkd3HnFXXdz4AA==", + "requires": { + "emojilib": "^2.0.2", + "iterate-object": "^1.3.1", + "map-o": "^2.0.1" + } + }, "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" }, "encodeurl": { "version": "1.0.2", @@ -20522,31 +4298,34 @@ } }, "engine.io": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", - "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "~7.4.2" + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" }, "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", "requires": { - "ms": "^2.1.1" + "@socket.io/base64-arraybuffer": "~1.0.2" } }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "requires": {} + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" } } }, @@ -20584,8 +4363,7 @@ "ws": { "version": "7.4.6", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "requires": {} + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" } } }, @@ -20610,6 +4388,11 @@ "ansi-colors": "^4.1.1" } }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -20617,6 +4400,14 @@ "dev": true, "requires": { "is-arrayish": "^0.2.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + } } }, "es-abstract": { @@ -20675,9 +4466,9 @@ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "escodegen": { @@ -20693,12 +4484,6 @@ "source-map": "~0.6.1" }, "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -20722,28 +4507,6 @@ "type-check": "~0.3.2", "word-wrap": "~1.2.3" } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } } } }, @@ -20804,96 +4567,15 @@ "@babel/highlight": "^7.10.4" } }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, "globals": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", - "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "version": "13.12.1", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", + "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", "dev": true, "requires": { "type-fest": "^0.20.2" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -20928,15 +4610,31 @@ "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } } }, "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { - "eslint-visitor-keys": "^2.0.0" + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } } }, "eslint-visitor-keys": { @@ -20977,14 +4675,6 @@ "dev": true, "requires": { "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } } }, "esrecurse": { @@ -20994,20 +4684,12 @@ "dev": true, "requires": { "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true - } } }, "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true }, "esutils": { @@ -21016,6 +4698,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "eta": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.0.0.tgz", + "integrity": "sha512-NqE7S2VmVwgMS8yBxsH4VgNQjNjLq1gfGU0u9I6Cjh468nPRMoDfGdK9n1p/3Dvsw3ebklDkZsFAnKJ9sefjBA==" + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -21057,6 +4744,17 @@ "onetime": "^5.1.0", "signal-exit": "^3.0.2", "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } } }, "exit": { @@ -21085,90 +4783,9 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true + "requires": { + "ms": "2.0.0" + } }, "ms": { "version": "2.0.0", @@ -21195,32 +4812,6 @@ "jest-matcher-utils": "^26.6.2", "jest-message-util": "^26.6.2", "jest-regex-util": "^26.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } } }, "extend": { @@ -21230,13 +4821,12 @@ "dev": true }, "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "is-extendable": "^0.1.0" } }, "extglob": { @@ -21263,21 +4853,6 @@ "requires": { "is-descriptor": "^1.0.0" } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true } } }, @@ -21298,9 +4873,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -21332,6 +4907,18 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fast-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-proxy/-/fast-proxy-2.1.0.tgz", + "integrity": "sha512-ihCPWH8j4pfSIULx6evT39RzZjCkGScCVn2BRyJElDu3v96NCWjPJPX8Olnzxv30mMQUEEijonTKroqCVpXjUQ==", + "requires": { + "end-of-stream": "^1.4.4", + "pump": "^3.0.0", + "semver": "^7.3.5", + "tiny-lru": "^7.0.6", + "undici": "^3.3.6" + } + }, "fast-redact": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", @@ -21356,20 +4943,20 @@ } }, "fastify": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.22.1.tgz", - "integrity": "sha512-TeA4+TzI7VuJrjTNqoxtSXwPEYfCwpT8j9Z3j9WrL8nrt+1bE9G0rP9hLJyvbg4it56p68YsHVhKOee69xyfmA==", + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.27.1.tgz", + "integrity": "sha512-GLn3ow5BGqg/m+ztXvztp8Xp7SuH99vAm4zfbN7407Qzi4mB055SG/lWH/gYolz5Oq2K8LtUpZqt1Ccf/YkVmA==", "requires": { "@fastify/ajv-compiler": "^1.0.0", "abstract-logging": "^2.0.0", "avvio": "^7.1.2", "fast-json-stringify": "^2.5.2", "fastify-error": "^0.3.0", - "fastify-warning": "^0.2.0", - "find-my-way": "^4.1.0", + "find-my-way": "^4.5.0", "flatstr": "^1.0.12", "light-my-request": "^4.2.0", "pino": "^6.13.0", + "process-warning": "^1.0.0", "proxy-addr": "^2.0.7", "rfdc": "^1.1.4", "secure-json-parse": "^2.0.0", @@ -21377,12 +4964,15 @@ "tiny-lru": "^7.0.0" }, "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "find-my-way": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.5.1.tgz", + "integrity": "sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg==", "requires": { - "lru-cache": "^6.0.0" + "fast-decode-uri-component": "^1.0.1", + "fast-deep-equal": "^3.1.3", + "safe-regex2": "^2.0.0", + "semver-store": "^0.3.0" } } } @@ -21436,16 +5026,17 @@ } }, "fastify-multipart": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fastify-multipart/-/fastify-multipart-4.0.3.tgz", - "integrity": "sha512-RyouqARMlSgTudcPCDmxVN07YEDWojT5iQ+AkjX7DcQ+Y65hHzrOqrNveu5gs+lEIg5afGaH5ESHCNCOZYlveQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/fastify-multipart/-/fastify-multipart-5.3.1.tgz", + "integrity": "sha512-c2pnGfkJmiNpYqzFYT2QfBg/06AxG531O+n1elqc8YUbWPRzufdqn3yfGAIV3RA7J4Vnf7Pfvgx0iaWqaRTOVA==", "requires": { - "busboy": "^0.3.1", + "@fastify/busboy": "^1.0.0", "deepmerge": "^4.2.2", "end-of-stream": "^1.4.4", "fastify-error": "^0.3.0", "fastify-plugin": "^3.0.0", "hexoid": "^1.0.0", + "secure-json-parse": "^2.4.0", "stream-wormhole": "^1.1.0" }, "dependencies": { @@ -21462,30 +5053,36 @@ "integrity": "sha512-I+Oaj6p9oiRozbam30sh39BiuiqBda7yK2nmSPVwDCfIBlKnT8YB3MY+pRQc2Fcd07bf6KPGklHJaQ2Qu81TYQ==", "requires": { "semver": "^7.3.2" - }, - "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "fastify-sensible": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fastify-sensible/-/fastify-sensible-3.1.1.tgz", - "integrity": "sha512-qWGsLEcc8VmLpbbWY7VJwXwWISsGBH9H4J2QeIc+l5Ov3a1lYs7ZaSnr0X8dkffdvzr9iy8wQyIuthpKTy5sZA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fastify-sensible/-/fastify-sensible-3.0.1.tgz", + "integrity": "sha512-XVgrQySnpNq6FTUEhLLyA0i6eB7DKF6OJV05gxCDQ008cEgzOs97L/TOd1tT3fgRf3Z6tyA2zb/wMdFX5o1C2Q==", "requires": { + "@types/node": "^14.0.1", "fast-deep-equal": "^3.1.1", - "fastify-plugin": "^3.0.0", + "fastify-plugin": "^2.0.0", "forwarded": "^0.1.2", "http-errors": "^1.7.3", "type-is": "^1.6.18", "vary": "^1.1.2" }, + "dependencies": { + "@types/node": { + "version": "14.18.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.16.tgz", + "integrity": "sha512-X3bUMdK/VmvrWdoTkz+VCn6nwKwrKCFTHtqwBIaQJNx4RUIBBUFXM00bqPz/DsDd+Icjmzm6/tyYZzeGVqb6/Q==" + } + } + }, + "fastify-socket.io": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fastify-socket.io/-/fastify-socket.io-3.0.0.tgz", + "integrity": "sha512-rVNs6NPY6ZoUQFMxZCRQreQpNyNkyKXrTbzXXzw55/grEegTW0meKBI02JAyWd2/T+k7nKB+d/7aNhYlB/Q5Bg==", + "requires": { + "fastify-plugin": "^3.0.0" + }, "dependencies": { "fastify-plugin": { "version": "3.0.0", @@ -21495,39 +5092,31 @@ } }, "fastify-static": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.2.3.tgz", - "integrity": "sha512-uFRgwYXZwLKyaMrByf10efO+HTjAPqyQOlUthoGljQKGCfbwUeTeE7EHadsDWeN7NMeqBE617RamVh9uqatuUw==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.7.0.tgz", + "integrity": "sha512-zZhCfJv/hkmud2qhWqpU3K9XVAuy3+IV8Tp9BC5J5U+GyA2XwoB6h8lh9GqpEIqdXOw01WyWQllV7dOWVyAlXg==", "requires": { - "content-disposition": "^0.5.3", - "encoding-negotiator": "^2.0.1", - "fastify-plugin": "^3.0.0", - "glob": "^7.1.4", - "readable-stream": "^3.4.0", - "send": "^0.17.1" + "fastify-static-deprecated": "npm:fastify-static@4.6.1", + "process-warning": "^1.0.0" }, "dependencies": { "fastify-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz", - "integrity": "sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w==" - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.1.tgz", + "integrity": "sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==" }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "fastify-static-deprecated": { + "version": "npm:fastify-static@4.6.1", + "resolved": "https://registry.npmjs.org/fastify-static/-/fastify-static-4.6.1.tgz", + "integrity": "sha512-vy7N28U4AMhuOim12ZZWHulEE6OQKtzZbHgiB8Zj4llUuUQXPka0WHAQI3njm1jTCx4W6fixUHfpITxweMtAIA==", "requires": { - "safe-buffer": "~5.2.0" + "content-disposition": "^0.5.3", + "encoding-negotiator": "^2.0.1", + "fastify-plugin": "^3.0.0", + "glob": "^7.1.4", + "p-limit": "^3.1.0", + "readable-stream": "^3.4.0", + "send": "^0.17.1" } } } @@ -21597,25 +5186,18 @@ } }, "fastparallel": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.0.tgz", - "integrity": "sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", + "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", "requires": { "reusify": "^1.0.4", "xtend": "^4.0.2" - }, - "dependencies": { - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - } } }, "fastq": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", - "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", "requires": { "reusify": "^1.0.4" } @@ -21627,13 +5209,6 @@ "requires": { "reusify": "^1.0.0", "xtend": "^4.0.0" - }, - "dependencies": { - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - } } }, "fb-watchman": { @@ -21654,6 +5229,11 @@ "flat-cache": "^3.0.4" } }, + "file-type": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.7.1.tgz", + "integrity": "sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -21664,9 +5244,9 @@ } }, "find-my-way": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-4.3.3.tgz", - "integrity": "sha512-5E4bRdaATB1MewjOCBjx4xvD205a4t2ripCnXB+YFhYEJ0NABtrcC7XLXLq0TPoFe/WYGUFqys3Qk3HCOGeNcw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-5.2.0.tgz", + "integrity": "sha512-YLocRSSJJ1PCnrupBmaw2pUcFkU125QTWfFfpdLq11h7bQ+r+Ke4D1/4v7UkERlw0037VkYMd+1RMGTbhFCbPw==", "requires": { "fast-decode-uri-component": "^1.0.1", "fast-deep-equal": "^3.1.3", @@ -21700,15 +5280,29 @@ "integrity": "sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw==" }, "flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "fluent-ffmpeg": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", + "integrity": "sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==", + "requires": { + "async": ">=0.2.9", + "which": "^1.1.1" + } + }, + "fold-to-ascii": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fold-to-ascii/-/fold-to-ascii-5.0.0.tgz", + "integrity": "sha512-HjtRWXC9aVit47DOEqvorgaQDiIyeX+frV3tM22RlllposIxnPXRM/vYoE6y6pwW57RdgahSe32Cu0vf4/UX1Q==" + }, "follow-redirects": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz", - "integrity": "sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==" + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" }, "for-in": { "version": "1.0.2", @@ -21742,9 +5336,9 @@ } }, "formidable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", - "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz", + "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==", "dev": true }, "forwarded": { @@ -21786,13 +5380,6 @@ "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } } }, "fs-minipass": { @@ -21846,6 +5433,24 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -21857,9 +5462,9 @@ } }, "generate-password": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/generate-password/-/generate-password-1.6.1.tgz", - "integrity": "sha512-JvtWSiN4KVmF6kBFi89Uz9LLN7l/EuGZYiKrIxddFlKcjSgc3D3va0Z5faooNwN85O0VBlt/ZtTdqhbQKhAOyw==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/generate-password/-/generate-password-1.7.0.tgz", + "integrity": "sha512-WPCtlfy0jexf7W5IbwxGUgpIDvsZIohbI2DAq2Q6TSlKKis+G4GT9sxvPxrZUGL8kP6WUXMWNqYnxY6DDKAdFA==" }, "gensync": { "version": "1.0.0-beta.2", @@ -21900,9 +5505,9 @@ "dev": true }, "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { "pump": "^3.0.0" @@ -21914,15 +5519,62 @@ "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", "dev": true }, + "get-website-favicon": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/get-website-favicon/-/get-website-favicon-0.0.7.tgz", + "integrity": "sha512-FD452CzghMhdMytp09Ax5R/IAi6835DcFsbF/kXNDa5Aep+aVN+c2kmy5wDTLPtY2Tnlh4eq1j6GgXtUGK3gYQ==", + "requires": { + "axios": "^0.18.0", + "cheerio": "^1.0.0-rc.2", + "file-type": "^7.6.0" + }, + "dependencies": { + "axios": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", + "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", + "requires": { + "follow-redirects": "1.5.10", + "is-buffer": "^2.0.2" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" }, "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -21957,23 +5609,23 @@ "dev": true }, "globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, "requires": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", "slash": "^3.0.0" }, "dependencies": { "ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true } } @@ -22015,14 +5667,6 @@ "yallist": "^2.1.2" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, "yallist": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", @@ -22049,13 +5693,13 @@ "url-parse-lax": "^3.0.0" }, "dependencies": { - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", "dev": true, "requires": { - "pump": "^3.0.0" + "mimic-response": "^1.0.0" } } } @@ -22106,10 +5750,9 @@ "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { "version": "1.0.2", @@ -22150,26 +5793,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -22187,6 +5810,11 @@ "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", "dev": true }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, "hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -22218,6 +5846,95 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "html-metadata-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/html-metadata-parser/-/html-metadata-parser-2.0.4.tgz", + "integrity": "sha512-pBjST/bbe3nuy/fNmvyY4G+ypukQ/QHiGc+YnS4up2OVnT4vI0CZA4x2J0Ri77sQkQGH2IMAAug0fE78FfDrLw==", + "requires": { + "axios": "^0.24.0", + "node-html-parser": "^5.2.0" + }, + "dependencies": { + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + } + } + }, + "html-to-text": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", + "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", + "requires": { + "@selderee/plugin-htmlparser2": "^0.6.0", + "deepmerge": "^4.2.2", + "he": "^1.2.0", + "htmlparser2": "^6.1.0", + "minimist": "^1.2.6", + "selderee": "^0.6.0" + }, + "dependencies": { + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + } + } + }, + "htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + } + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -22225,15 +5942,22 @@ "dev": true }, "http-errors": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", - "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", "requires": { "depd": "~1.1.2", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" + "toidentifier": "1.0.1" + }, + "dependencies": { + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + } } }, "http-proxy-agent": { @@ -22266,7 +5990,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } @@ -22374,6 +6097,14 @@ "dev": true, "requires": { "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "is-arguments": { @@ -22386,10 +6117,9 @@ } }, "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "is-bigint": { "version": "1.0.4", @@ -22452,6 +6182,14 @@ "dev": true, "requires": { "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "is-date-object": { @@ -22471,6 +6209,14 @@ "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "is-docker": { @@ -22480,15 +6226,12 @@ "dev": true, "optional": true }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -22496,12 +6239,9 @@ "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-generator-fn": { "version": "2.1.0", @@ -22553,10 +6293,13 @@ "dev": true }, "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, "is-number-object": { "version": "1.0.6", @@ -22578,6 +6321,11 @@ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -22675,9 +6423,9 @@ "dev": true }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -22706,6 +6454,14 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "istanbul-lib-report": { @@ -22717,23 +6473,6 @@ "istanbul-lib-coverage": "^3.0.0", "make-dir": "^3.0.0", "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "istanbul-lib-source-maps": { @@ -22745,14 +6484,6 @@ "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "istanbul-reports": { @@ -22765,6 +6496,11 @@ "istanbul-lib-report": "^3.0.0" } }, + "iterate-object": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/iterate-object/-/iterate-object-1.3.4.tgz", + "integrity": "sha512-4dG1D1x/7g8PwHS9aK6QV5V94+ZvyP4+d19qDv43EzImmrndysIl4prmJ1hWWIGCqrZHyaHBm6BSEWHOLnpoNw==" + }, "jest": { "version": "26.6.3", "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz", @@ -22808,25 +6544,6 @@ "yargs": "^15.4.1" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -22838,59 +6555,6 @@ "wrap-ansi": "^6.2.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -22900,6 +6564,19 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "dependencies": { + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } } }, "y18n": { @@ -22963,57 +6640,6 @@ "jest-validate": "^26.6.2", "micromatch": "^4.0.2", "pretty-format": "^26.6.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-diff": { @@ -23026,57 +6652,6 @@ "diff-sequences": "^26.6.2", "jest-get-type": "^26.3.0", "pretty-format": "^26.6.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-docblock": { @@ -23099,57 +6674,6 @@ "jest-get-type": "^26.3.0", "jest-util": "^26.6.2", "pretty-format": "^26.6.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-environment-jsdom": { @@ -23218,72 +6742,21 @@ "@babel/traverse": "^7.1.0", "@jest/environment": "^26.6.2", "@jest/source-map": "^26.6.2", - "@jest/test-result": "^26.6.2", - "@jest/types": "^26.6.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^26.6.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^26.6.2", - "jest-matcher-utils": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-runtime": "^26.6.3", - "jest-snapshot": "^26.6.2", - "jest-util": "^26.6.2", - "pretty-format": "^26.6.2", - "throat": "^5.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.6.2", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-runtime": "^26.6.3", + "jest-snapshot": "^26.6.2", + "jest-util": "^26.6.2", + "pretty-format": "^26.6.2", + "throat": "^5.0.0" } }, "jest-leak-detector": { @@ -23306,57 +6779,6 @@ "jest-diff": "^26.6.2", "jest-get-type": "^26.3.0", "pretty-format": "^26.6.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-message-util": { @@ -23374,57 +6796,6 @@ "pretty-format": "^26.6.2", "slash": "^3.0.0", "stack-utils": "^2.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-mock": { @@ -23441,8 +6812,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true, - "requires": {} + "dev": true }, "jest-regex-util": { "version": "26.0.0", @@ -23464,57 +6834,6 @@ "read-pkg-up": "^7.0.1", "resolve": "^1.18.1", "slash": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-resolve-dependencies": { @@ -23554,57 +6873,6 @@ "jest-worker": "^26.6.2", "source-map-support": "^0.5.6", "throat": "^5.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-runtime": { @@ -23642,25 +6910,6 @@ "yargs": "^15.4.1" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -23672,59 +6921,12 @@ "wrap-ansi": "^6.2.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "has-flag": { + "strip-bom": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -23734,6 +6936,19 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" + }, + "dependencies": { + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + } } }, "y18n": { @@ -23798,73 +7013,13 @@ "graceful-fs": "^4.2.4", "jest-diff": "^26.6.2", "jest-get-type": "^26.3.0", - "jest-haste-map": "^26.6.2", - "jest-matcher-utils": "^26.6.2", - "jest-message-util": "^26.6.2", - "jest-resolve": "^26.6.2", - "natural-compare": "^1.4.0", - "pretty-format": "^26.6.2", - "semver": "^7.3.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "jest-haste-map": "^26.6.2", + "jest-matcher-utils": "^26.6.2", + "jest-message-util": "^26.6.2", + "jest-resolve": "^26.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^26.6.2", + "semver": "^7.3.2" } }, "jest-util": { @@ -23879,57 +7034,6 @@ "graceful-fs": "^4.2.4", "is-ci": "^2.0.0", "micromatch": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-validate": { @@ -23946,60 +7050,17 @@ "pretty-format": "^26.6.2" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "camelcase": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", "dev": true }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -24016,57 +7077,6 @@ "chalk": "^4.0.0", "jest-util": "^26.6.2", "string-length": "^4.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jest-worker": { @@ -24078,23 +7088,6 @@ "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "jmespath": { @@ -24217,6 +7210,11 @@ "resolved": "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz", "integrity": "sha1-GjhU4o0rvuqzHMfd9oPS3cVlJwg=" }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -24232,13 +7230,6 @@ "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" - }, - "dependencies": { - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } } }, "jsonwebtoken": { @@ -24294,10 +7285,13 @@ } }, "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } }, "kleur": { "version": "3.0.3", @@ -24315,9 +7309,9 @@ } }, "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=", "dev": true }, "levn": { @@ -24328,6 +7322,23 @@ "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" + }, + "dependencies": { + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + } } }, "light-my-request": { @@ -24357,24 +7368,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } } } }, @@ -24443,8 +7436,7 @@ "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" }, "lodash.once": { "version": "4.1.1", @@ -24464,51 +7456,6 @@ "requires": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } } }, "long": { @@ -24522,11 +7469,6 @@ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", "dev": true }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" - }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -24535,12 +7477,24 @@ "yallist": "^4.0.0" } }, + "lru_map": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", + "integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0=" + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "requires": { "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } } }, "make-error": { @@ -24564,6 +7518,14 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-o": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/map-o/-/map-o-2.0.10.tgz", + "integrity": "sha512-BxazE81fVByHWasyXhqKeo2m7bFKYu+ZbEfiuexMOnklXW+tzDvnlTi/JaklEeuuwqcqJzPaf9q+TWptSGXeLg==", + "requires": { + "iterate-object": "^1.3.0" + } + }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -24605,6 +7567,14 @@ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", "optional": true }, + "merge-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-1.0.1.tgz", + "integrity": "sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg==", + "requires": { + "is-plain-obj": "^1.1" + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -24671,9 +7641,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" }, "minio": { "version": "7.0.19", @@ -24693,6 +7663,16 @@ "web-encoding": "^1.1.5", "xml": "^1.0.0", "xml2js": "^0.4.15" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } } }, "minipass": { @@ -24720,15 +7700,23 @@ "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "mkdirp-classic": { "version": "0.5.3", @@ -24736,9 +7724,9 @@ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" }, "moment-timezone": { "version": "0.5.33", @@ -24768,6 +7756,11 @@ "whatwg-url": "^8.4.0" } }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + }, "mri": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz", @@ -24786,26 +7779,6 @@ "requires": { "once": "^1.4.0", "readable-stream": "^3.6.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } } }, "nanomatch": { @@ -24825,6 +7798,43 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } } }, "napi-build-utils": { @@ -24838,6 +7848,37 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + } + }, + "needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -24850,18 +7891,11 @@ "dev": true }, "node-abi": { - "version": "2.30.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", - "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.24.0.tgz", + "integrity": "sha512-YPG3Co0luSu6GwOBsmIdGW6Wx0NyNDLg/hriIyDllVsNwnI6UeqaWShxC3lbH4LtEQUgoLP3XR1ndXiDAWvmRw==", "requires": { - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "semver": "^7.3.5" } }, "node-addon-api": { @@ -24869,6 +7903,14 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, "node-cleanup": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", @@ -24884,9 +7926,9 @@ } }, "node-fetch": { - "version": "2.6.6", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", - "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", "requires": { "whatwg-url": "^5.0.0" }, @@ -24912,6 +7954,62 @@ } } }, + "node-html-parser": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.3.3.tgz", + "integrity": "sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw==", + "requires": { + "css-select": "^4.2.1", + "he": "1.2.0" + }, + "dependencies": { + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + } + } + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -24939,14 +8037,14 @@ "which": "^2.0.2" }, "dependencies": { - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "optional": true, "requires": { - "lru-cache": "^6.0.0" + "isexe": "^2.0.0" } } } @@ -24989,11 +8087,26 @@ "ms": "^2.1.1" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } } } }, @@ -25049,6 +8162,14 @@ "dev": true, "requires": { "path-key": "^3.0.0" + }, + "dependencies": { + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + } } }, "npmlog": { @@ -25062,6 +8183,14 @@ "set-blocking": "~2.0.0" } }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", @@ -25087,63 +8216,6 @@ "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "object-inspect": { @@ -25226,6 +8298,23 @@ "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.3" + }, + "dependencies": { + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + } } }, "ora": { @@ -25242,51 +8331,6 @@ "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } } }, "p-cancelable": { @@ -25308,12 +8352,11 @@ "dev": true }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "requires": { - "p-try": "^2.0.0" + "yocto-queue": "^0.1.0" } }, "p-locate": { @@ -25323,6 +8366,17 @@ "dev": true, "requires": { "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } } }, "p-try": { @@ -25341,6 +8395,14 @@ "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "parent-module": { @@ -25370,6 +8432,34 @@ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "dependencies": { + "parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "requires": { + "entities": "^4.3.0" + } + } + } + }, + "parseley": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", + "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", + "requires": { + "moo": "^0.5.1", + "nearley": "^2.20.1" + } + }, "parseqs": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", @@ -25398,9 +8488,9 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, "path-parse": { @@ -25456,17 +8546,6 @@ "pino-std-serializers": "^3.1.0", "quick-format-unescaped": "^4.0.3", "sonic-boom": "^1.0.2" - }, - "dependencies": { - "sonic-boom": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", - "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", - "requires": { - "atomic-sleep": "^1.0.0", - "flatstr": "^1.0.12" - } - } } }, "pino-pretty": { @@ -25486,78 +8565,7 @@ "readable-stream": "^3.6.0", "rfdc": "^1.3.0", "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "strip-json-comments": "^3.1.1" } }, "pino-std-serializers": { @@ -25590,29 +8598,28 @@ "dev": true }, "prebuild-install": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", - "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", + "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", "requires": { - "detect-libc": "^1.0.3", + "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", - "node-abi": "^2.21.0", - "npmlog": "^4.0.1", + "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", - "simple-get": "^3.0.3", + "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" } }, "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, "prepend-http": { @@ -25646,32 +8653,16 @@ "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^17.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + } + }, + "probe-image-size": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz", + "integrity": "sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==", + "requires": { + "lodash.merge": "^4.6.2", + "needle": "^2.5.2", + "stream-parser": "~0.3.1" } }, "process-nextick-args": { @@ -25679,6 +8670,11 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "process-warning": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", + "integrity": "sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -25794,6 +8790,48 @@ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==" }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "dependencies": { + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + } + } + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==" + }, + "random-seed": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/random-seed/-/random-seed-0.3.0.tgz", + "integrity": "sha512-y13xtn3kcTlLub3HKWXxJNeC2qK4mB59evwZ5EkeRlolx+Bp2ztF7LbcZmyCnOqlHQrLnfuNbi1sVmm9lPDlDA==", + "requires": { + "json-stringify-safe": "^5.0.1" + } + }, + "random-useragent": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/random-useragent/-/random-useragent-0.5.0.tgz", + "integrity": "sha512-FUMkqVdZeoSff5tErNL3FFGYXElDWZ1bEuedhm5u9MdCFwANriJWbHvDRYrLTOzp/fBsBGu5J1cWtDgifa97aQ==", + "requires": { + "random-seed": "^0.3.0" + } + }, "range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -25852,25 +8890,16 @@ "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } } }, "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, "readdirp": { @@ -25954,6 +8983,27 @@ "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "regexpp": { @@ -26189,8 +9239,7 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "sane": { "version": "4.1.0", @@ -26245,6 +9294,12 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, @@ -26261,6 +9316,16 @@ "which": "^1.2.9" } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, "execa": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", @@ -26276,6 +9341,16 @@ "strip-eof": "^1.0.0" } }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -26296,42 +9371,22 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true } } }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-plain-object": "^2.0.4" } }, "is-stream": { @@ -26340,6 +9395,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -26379,12 +9440,6 @@ "path-key": "^2.0.0" } }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -26415,15 +9470,6 @@ "is-number": "^3.0.0", "repeat-string": "^1.6.1" } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, @@ -26455,10 +9501,21 @@ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==" }, + "selderee": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", + "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", + "requires": { + "parseley": "^0.7.0" + } + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } }, "semver-diff": { "version": "3.1.1", @@ -26467,6 +9524,14 @@ "dev": true, "requires": { "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "semver-store": { @@ -26553,23 +9618,6 @@ "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } } }, "setprototypeof": { @@ -26578,29 +9626,29 @@ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "sharp": { - "version": "0.29.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.29.1.tgz", - "integrity": "sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ==", - "requires": { - "color": "^4.0.1", - "detect-libc": "^1.0.3", - "node-addon-api": "^4.1.0", - "prebuild-install": "^6.1.4", - "semver": "^7.3.5", - "simple-get": "^3.1.0", + "version": "0.30.7", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.30.7.tgz", + "integrity": "sha512-G+MY2YW33jgflKPTXXptVO28HvNOo9G3j0MybYAHeEmby+QuD2U98dT6ueht9cv/XDqZspSpIhoSW+BAKJ7Hig==", + "requires": { + "color": "^4.2.3", + "detect-libc": "^2.0.1", + "node-addon-api": "^5.0.0", + "prebuild-install": "^7.1.1", + "semver": "^7.3.7", + "simple-get": "^4.0.1", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" }, "dependencies": { "node-addon-api": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.2.0.tgz", - "integrity": "sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz", + "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", "requires": { "lru-cache": "^6.0.0" } @@ -26650,43 +9698,21 @@ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" }, "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", "requires": { - "decompress-response": "^4.2.0", + "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" - }, - "dependencies": { - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "requires": { - "mimic-response": "^2.0.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" - } } }, "simple-swizzle": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "requires": { "is-arrayish": "^0.3.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" - } } }, "sisteransi": { @@ -26710,38 +9736,6 @@ "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - } } }, "snapdragon": { @@ -26762,99 +9756,24 @@ "dependencies": { "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "ms": "2.0.0" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true } } }, @@ -26887,66 +9806,25 @@ "dev": true, "requires": { "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "socket.io": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", - "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", "requires": { - "debug": "~4.1.0", - "engine.io": "~3.5.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.4.0", - "socket.io-parser": "~3.4.0" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", - "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - } - } + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" } }, "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" }, "socket.io-client": { "version": "2.4.0", @@ -27000,57 +9878,25 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", - "dev": true, "requires": { "@types/component-emitter": "^1.2.10", "component-emitter": "~1.3.0", "debug": "~4.3.1" } }, - "socket.io-redis": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/socket.io-redis/-/socket.io-redis-5.4.0.tgz", - "integrity": "sha512-yCQm/Sywd3d08WXUfZRxt6O+JV2vWoPgWK6GVjiM0GkBtq5cpLOk8oILRPKbzTv1VEtSYmK41q0xzcgDinMbmQ==", - "requires": { - "debug": "~4.1.0", - "notepack.io": "~2.2.0", - "redis": "^3.0.0", - "socket.io-adapter": "~1.1.0", - "uid2": "0.0.3" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "socketio-jwt": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/socketio-jwt/-/socketio-jwt-4.6.2.tgz", - "integrity": "sha512-bcCnit/cCvqtC921Gwuqor+LpLKrpREmPACVgLfdbFBL95w2nPF7lOxsOxyeRrhc5Kot/1jUSW5+kLo23zJIMA==", - "requires": { - "jsonwebtoken": "^8.3.0", - "xtend": "~2.1.2" - } - }, "sonic-boom": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.1.0.tgz", - "integrity": "sha512-x2j9LXx27EDlyZEC32gBM+scNVMdPutU7FIKV2BOTKCnPrp7bY5BsplCMQ4shYYR3IhDSIrEXoqb6GlS+z7KyQ==", - "dev": true, + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz", + "integrity": "sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg==", "requires": { - "atomic-sleep": "^1.0.0" + "atomic-sleep": "^1.0.0", + "flatstr": "^1.0.12" } }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "source-map-resolve": { @@ -27074,14 +9920,6 @@ "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } } }, "source-map-url": { @@ -27147,39 +9985,38 @@ "dev": true, "requires": { "extend-shallow": "^3.0.0" - } - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" }, "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" } }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "is-plain-object": "^2.0.4" } } } }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -27211,74 +10048,6 @@ "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } } }, "statuses": { @@ -27307,21 +10076,34 @@ "duplexer": "~0.1.1" } }, + "stream-parser": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz", + "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==", + "requires": { + "debug": "2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, "stream-wormhole": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==" }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - }, "string-argv": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz", @@ -27344,28 +10126,13 @@ "integrity": "sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==" }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "string.prototype.trimend": { @@ -27386,18 +10153,26 @@ "define-properties": "^1.1.3" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "requires": { - "ansi-regex": "^5.0.0" + "ansi-regex": "^5.0.1" } }, "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-eof": { @@ -27456,12 +10231,6 @@ "mime-types": "^2.1.12" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -27505,39 +10274,21 @@ } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" } }, "symbol-tree": { @@ -27572,34 +10323,11 @@ "uri-js": "^4.2.2" } }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } } } }, @@ -27616,10 +10344,10 @@ "yallist": "^4.0.0" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" } } }, @@ -27632,13 +10360,6 @@ "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" - }, - "dependencies": { - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - } } }, "tar-stream": { @@ -27651,26 +10372,6 @@ "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } } }, "term-size": { @@ -27700,6 +10401,11 @@ "minimatch": "^3.0.4" } }, + "text-decoding": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", + "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -27725,26 +10431,6 @@ "requires": { "inherits": "^2.0.4", "readable-stream": "2 || 3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } } }, "tiny-lru": { @@ -27753,9 +10439,9 @@ "integrity": "sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==" }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "dev": true }, "to-array": { @@ -27776,17 +10462,6 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, "to-readable-stream": { @@ -27805,6 +10480,37 @@ "extend-shallow": "^3.0.2", "regex-not": "^1.0.2", "safe-regex": "^1.1.0" + }, + "dependencies": { + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, "to-regex-range": { @@ -27814,6 +10520,14 @@ "dev": true, "requires": { "is-number": "^7.0.0" + }, + "dependencies": { + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + } } }, "toidentifier": { @@ -27850,6 +10564,14 @@ "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.1.2" + }, + "dependencies": { + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } } }, "tr46": { @@ -27882,23 +10604,6 @@ "mkdirp": "1.x", "semver": "7.x", "yargs-parser": "20.x" - }, - "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "ts-node": { @@ -27933,12 +10638,6 @@ "tsconfig": "^7.0.0" }, "dependencies": { - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -27975,12 +10674,6 @@ "strip-json-comments": "^2.0.0" }, "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -28006,18 +10699,18 @@ "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", "requires": { "safe-buffer": "^5.0.1" } }, "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "^1.2.1" + "prelude-ls": "~1.1.2" } }, "type-detect": { @@ -28026,9 +10719,9 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true }, "type-is": { @@ -28055,6 +10748,14 @@ "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, "uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", @@ -28097,6 +10798,11 @@ } } }, + "undici": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/undici/-/undici-3.3.6.tgz", + "integrity": "sha512-/j3YTZ5AobMB4ZrTY72mzM54uFUX32v0R/JRW9G2vOyF1uSKYAx+WT8dMsAcRS13TOFISv094TxIyWYk+WEPsA==" + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -28135,14 +10841,6 @@ "get-value": "^2.0.6", "is-extendable": "^0.1.1", "set-value": "^2.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - } } }, "unique-string": { @@ -28155,10 +10853,9 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "unoconv-promise": { "version": "1.0.8", @@ -28214,12 +10911,6 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true } } }, @@ -28244,15 +10935,6 @@ "xdg-basedir": "^4.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -28262,36 +10944,6 @@ "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -28310,9 +10962,9 @@ "dev": true }, "url-parse": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", - "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" @@ -28476,10 +11128,9 @@ } }, "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { "isexe": "^2.0.0" } @@ -28521,42 +11172,50 @@ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "requires": { "string-width": "^1.0.2 || 2" - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "requires": { - "string-width": "^4.0.0" }, "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" } } } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -28573,45 +11232,14 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" + "strip-ansi": "^6.0.1" } } } @@ -28636,8 +11264,7 @@ "ws": { "version": "7.5.3", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "requires": {} + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==" }, "xdg-basedir": { "version": "4.0.0", @@ -28682,19 +11309,9 @@ "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==" }, "xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "requires": { - "object-keys": "~0.4.0" - }, - "dependencies": { - "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" - } - } + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { "version": "5.0.8", @@ -28718,28 +11335,6 @@ "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - } } }, "yargs-parser": { @@ -28757,6 +11352,11 @@ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/twake/backend/node/package.json b/twake/backend/node/package.json index d3610530e5..d77374741c 100644 --- a/twake/backend/node/package.json +++ b/twake/backend/node/package.json @@ -6,8 +6,9 @@ "build": "npm run build:clean && npm run build:ts && npm run build:copy-assets", "build:ts": "tsc", "build:clean": "rimraf ./dist", - "build:copy-assets": "npm run build:copy-config", + "build:copy-assets": "npm run build:copy-config && npm run build:copy-templates", "build:copy-config": "cp -R config dist", + "build:copy-templates": "cpy src/**/*.eta dist/", "dev": "tsc-watch --project . --noClear --outDir ./dist --onSuccess \"nodemon ./dist/server.js\" | pino-pretty", "dev:cli": "tsc-watch --project . --noClear --outDir ./dist --onSuccess \"nodemon ./dist/cli/index.js workspace user\" | pino-pretty", "dev:cli-dry": "tsc-watch --project . --noClear --outDir ./dist --onSuccess \"nodemon ./dist/cli/index.js console merge --dry\" | pino-pretty", @@ -20,6 +21,7 @@ "serve:debug": "nodemon --inspect dist/server.js | pino-pretty", "start": "npm run serve", "test": "jest --forceExit --coverage --detectOpenHandles --runInBand --verbose false | pino-pretty", + "test:local": "jest --forceExit --detectOpenHandles --runInBand mock.spec.ts", "test:watch": "npm run test -- --watchAll --verbose false | pino-pretty", "test:e2e": "node ./test/e2e/run-all.js", "test:unit": "jest test/unit --forceExit --coverage --detectOpenHandles --maxWorkers=1 --testTimeout=30000 --verbose false", @@ -58,20 +60,23 @@ "@types/config": "0.0.36", "@types/eslint": "^7.2.3", "@types/fastify-multipart": "^0.7.0", + "@types/fastify-static": "^2.2.1", + "@types/fluent-ffmpeg": "^2.1.20", + "@types/html-to-text": "^8.1.1", "@types/jest": "^26.0.14", "@types/lodash": "^4.14.165", "@types/minio": "^7.0.7", "@types/mongodb": "^4.0.7", "@types/node": "^14.11.2", "@types/node-cron": "^3.0.0", - "@types/node-fetch": "^2.5.10", + "@types/node-fetch": "^2.5.12", "@types/node-uuid": "^0.0.28", "@types/pdf-image": "^2.0.1", "@types/pino": "^6.3.2", - "@types/sharp": "^0.28.5", - "@types/socket.io": "^2.1.11", + "@types/probe-image-size": "^7.0.1", + "@types/pump": "^1.1.1", + "@types/random-useragent": "^0.3.1", "@types/socket.io-client": "^1.4.34", - "@types/socket.io-redis": "^1.0.26", "@types/supertest": "2.0.4", "@types/uuid": "^8.3.0", "@types/ws": "^7.2.7", @@ -80,6 +85,7 @@ "babel-jest": "^26.5.2", "babel-plugin-parameter-decorator": "^1.0.16", "chai": "^4.2.0", + "cpy-cli": "^4.2.0", "eslint": "^7.10.0", "eslint-config-prettier": "^6.15.0", "eslint-plugin-prettier": "^3.1.4", @@ -98,10 +104,18 @@ }, "dependencies": { "@elastic/elasticsearch": "7", - "@sentry/node": "^6.13.3", - "@sentry/tracing": "^6.13.3", + "@fastify/caching": "^7.0.0", + "@fastify/formbody": "^6.0.0", + "@fastify/static": "^5.0.1", + "@ffprobe-installer/ffprobe": "^1.4.1", + "@sentry/node": "^6.15.0", + "@sentry/tracing": "^6.15.0", + "@socket.io/redis-adapter": "^7.1.0", + "@types/redis": "^4.0.11", + "@types/sharp": "^0.29.5", + "@types/socket.io-parser": "^3.0.0", "amqp-connection-manager": "^3.7.0", - "amqplib": "^0.7.1", + "amqplib": "^0.8.0", "analytics-node": "^5.0.0", "axios": "^0.21.3", "bcrypt": "^5.0.1", @@ -110,35 +124,50 @@ "cli-table": "^0.3.6", "config": "^3.3.2", "deep-object-diff": "^1.1.0", - "fastify": "3.22.1", + "emoji-name-map": "^1.2.9", + "eta": "^2.0.0", + "fast-proxy": "^2.1.0", + "fastify": "^3.27.1", "fastify-cors": "^4.1.0", "fastify-formbody": "^5.0.0", "fastify-jwt": "^2.2.0", - "fastify-multipart": "4.0.3", + "fastify-multipart": "5.3.1", "fastify-plugin": "^2.3.4", - "fastify-sensible": "^3.0.1", + "fastify-sensible": "=3.0.1", + "fastify-socket.io": "^3.0.0", + "fastify-static": "^4.7.0", "fastify-swagger": "^4.12.6", "fastify-websocket": "^2.0.11", + "find-my-way": "^5.2.0", + "fluent-ffmpeg": "^2.1.2", + "fold-to-ascii": "^5.0.0", "generate-password": "^1.6.0", + "get-website-favicon": "^0.0.7", + "html-metadata-parser": "^2.0.4", + "html-to-text": "^8.2.1", + "jsonwebtoken": "^8.5.1", "lodash": "^4.17.21", "match-all": "^1.2.6", "minio": "^7.0.18", - "moment": "^2.29.1", + "moment": "^2.29.4", "mongodb": "^4.1.0", "multistream": "^4.1.0", + "node-cache": "^5.1.2", "node-cron": "^3.0.0", - "node-fetch": "^2.6.5", + "node-fetch": "^2.6.7", "node-uuid": "^1.4.8", "ora": "^5.4.0", "pdf2pic": "^2.1.4", "pino": "^6.8.0", + "probe-image-size": "^7.2.3", + "pump": "^3.0.0", + "random-useragent": "^0.5.0", + "redis": "3", "reflect-metadata": "^0.1.13", "rxjs": "^6.6.3", - "sharp": "^0.29.0", - "socket.io": "^2.3.0", + "sharp": "^0.30.5", + "socket.io": "4", "socket.io-client": "^2.3.1", - "socket.io-redis": "^5.4.0", - "socketio-jwt": "^4.6.2", "unoconv-promise": "^1.0.8", "uuid": "^8.3.2", "uuid-time": "^1.0.0", diff --git a/twake/backend/node/src/@types/emoji-name-map.ts b/twake/backend/node/src/@types/emoji-name-map.ts new file mode 100644 index 0000000000..163b970749 --- /dev/null +++ b/twake/backend/node/src/@types/emoji-name-map.ts @@ -0,0 +1 @@ +declare module "emoji-name-map"; diff --git a/twake/backend/node/src/@types/get-website-favicon.ts b/twake/backend/node/src/@types/get-website-favicon.ts new file mode 100644 index 0000000000..0e02735f4f --- /dev/null +++ b/twake/backend/node/src/@types/get-website-favicon.ts @@ -0,0 +1 @@ +declare module "get-website-favicon"; diff --git a/twake/backend/node/src/cli/cmds/applications_cmds/ls.ts b/twake/backend/node/src/cli/cmds/applications_cmds/ls.ts index ab74d8df82..a4846d1699 100644 --- a/twake/backend/node/src/cli/cmds/applications_cmds/ls.ts +++ b/twake/backend/node/src/cli/cmds/applications_cmds/ls.ts @@ -2,23 +2,23 @@ import yargs from "yargs"; import ora from "ora"; import twake from "../../../twake"; import Table from "cli-table"; -import { ApplicationServiceAPI } from "../../../services/applications/api"; import * as process from "process"; +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. */ -type CLIArgs = {}; +type CLIArgs = Record; const services = [ "storage", "counter", - "pubsub", + "message-queue", "platform-services", "applications", - // "auth", - // "realtime", - // "websocket", + "auth", + "realtime", + "websocket", // "user", "search", "database", @@ -33,15 +33,15 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Retrieving applications" }).start(); const platform = await twake.run(services); - const applicationService = platform.getProvider("applications"); + await gr.doInit(platform); // - const unpublished = await applicationService.applications.listUnpublished(); + const unpublished = await gr.services.applications.marketplaceApps.listUnpublished(undefined); // const table = new Table({ head: ["ID", "Name", "Description"], colWidths: [40, 20, 40], }); - unpublished.forEach(app => { + unpublished.forEach((app: any) => { table.push([app.id, app.identity.name, app.identity.description]); }); spinner.stop(); @@ -51,6 +51,4 @@ const command: yargs.CommandModule = { }, }; -const showUnpublishedApplications = async () => {}; - export default command; diff --git a/twake/backend/node/src/cli/cmds/applications_cmds/publish.ts b/twake/backend/node/src/cli/cmds/applications_cmds/publish.ts index 345e38819c..18d88fc30d 100644 --- a/twake/backend/node/src/cli/cmds/applications_cmds/publish.ts +++ b/twake/backend/node/src/cli/cmds/applications_cmds/publish.ts @@ -2,9 +2,8 @@ import yargs from "yargs"; import ora from "ora"; import twake from "../../../twake"; import Table from "cli-table"; -import { ApplicationServiceAPI } from "../../../services/applications/api"; import * as process from "process"; - +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. */ @@ -15,17 +14,17 @@ type CLIArgs = { const services = [ "storage", "counter", - "pubsub", + "message-queue", "platform-services", "applications", - // "auth", - // "realtime", - // "websocket", - // "user", + "auth", + "realtime", + "websocket", + "user", "search", "database", "webserver", - // "statistics", + "statistics", ]; const command: yargs.CommandModule = { @@ -43,8 +42,8 @@ const command: yargs.CommandModule = { if (argv.id) { let spinner = ora({ text: "Retrieving application" }).start(); const platform = await twake.run(services); - const service = platform.getProvider("applications"); - let app = await service.applications.get({ id: argv.id }); + await gr.doInit(platform); + let app = await gr.services.applications.marketplaceApps.get({ id: argv.id }, undefined); spinner.stop(); if (!app) { console.error(`Application ${argv.id} not found`); @@ -72,8 +71,8 @@ const command: yargs.CommandModule = { } spinner = ora({ text: "Publishing application" }).start(); - await service.applications.publish({ id: argv.id }); - app = await service.applications.get({ id: argv.id }); + await gr.services.applications.marketplaceApps.publish({ id: argv.id }, undefined); + app = await gr.services.applications.marketplaceApps.get({ id: argv.id }, undefined); spinner.stop(); console.log("Application published"); diff --git a/twake/backend/node/src/cli/cmds/applications_cmds/unpublish.ts b/twake/backend/node/src/cli/cmds/applications_cmds/unpublish.ts index ddf08c5e68..2e8b927c96 100644 --- a/twake/backend/node/src/cli/cmds/applications_cmds/unpublish.ts +++ b/twake/backend/node/src/cli/cmds/applications_cmds/unpublish.ts @@ -2,9 +2,8 @@ import yargs from "yargs"; import ora from "ora"; import twake from "../../../twake"; import Table from "cli-table"; -import { ApplicationServiceAPI } from "../../../services/applications/api"; import * as process from "process"; - +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. */ @@ -15,17 +14,17 @@ type CLIArgs = { const services = [ "storage", "counter", - "pubsub", + "message-queue", "platform-services", "applications", - // "auth", - // "realtime", - // "websocket", - // "user", + "auth", + "realtime", + "websocket", + "user", "search", "database", "webserver", - // "statistics", + "statistics", ]; const command: yargs.CommandModule = { @@ -35,8 +34,8 @@ const command: yargs.CommandModule = { if (argv.id) { let spinner = ora({ text: "Retrieving application" }).start(); const platform = await twake.run(services); - const service = platform.getProvider("applications"); - let app = await service.applications.get({ id: argv.id }); + await gr.doInit(platform); + let app = await gr.services.applications.marketplaceApps.get({ id: argv.id }, undefined); spinner.stop(); if (!app) { console.error(`Application ${argv.id} not found`); @@ -57,8 +56,8 @@ const command: yargs.CommandModule = { } spinner = ora({ text: "Unpublishing application" }).start(); - await service.applications.unpublish({ id: argv.id }); - app = await service.applications.get({ id: argv.id }); + await gr.services.applications.marketplaceApps.unpublish({ id: argv.id }, undefined); + app = await gr.services.applications.marketplaceApps.get({ id: argv.id }, undefined); spinner.stop(); console.log("Application unpublished"); diff --git a/twake/backend/node/src/cli/cmds/console_cmds/merge.ts b/twake/backend/node/src/cli/cmds/console_cmds/merge.ts index a0b39a5138..c6e093e53b 100644 --- a/twake/backend/node/src/cli/cmds/console_cmds/merge.ts +++ b/twake/backend/node/src/cli/cmds/console_cmds/merge.ts @@ -1,9 +1,10 @@ import yargs from "yargs"; import ora from "ora"; import twake from "../../../twake"; -import { ConsoleServiceAPI } from "../../../services/console/api"; import { CompanyReport, UserReport } from "../../../services/console/types"; import Company from "../../../services/user/entities/company"; +import gr from "../../../services/global-resolver"; +import { ConsoleServiceImpl } from "../../../services/console/service"; /** * Merge command parameters. Check the builder definition below for more details. @@ -26,7 +27,7 @@ const services = [ "notifications", "database", "webserver", - "pubsub", + "message-queue", "console", ]; @@ -80,7 +81,8 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: `Importing Twake data on ${argv.url}` }).start(); const platform = await twake.run(services); - const consoleService = platform.getProvider("console"); + await gr.doInit(platform); + const consoleService = platform.getProvider("console"); const merge = consoleService.merge( argv.url, argv.concurrent, diff --git a/twake/backend/node/src/cli/cmds/export_cmds/export_company.ts b/twake/backend/node/src/cli/cmds/export_cmds/export_company.ts index c5ac626b34..6d68b86344 100644 --- a/twake/backend/node/src/cli/cmds/export_cmds/export_company.ts +++ b/twake/backend/node/src/cli/cmds/export_cmds/export_company.ts @@ -1,18 +1,15 @@ import yargs from "yargs"; import twake from "../../../twake"; -import UserServiceAPI from "../../../services/user/api"; import { mkdirSync, writeFileSync } from "fs"; -import { WorkspaceServiceAPI } from "../../../services/workspaces/api"; import { Pagination } from "../../../core/platform/framework/api/crud-service"; import WorkspaceUser from "../../../services/workspaces/entities/workspace_user"; -import { ApplicationServiceAPI } from "../../../services/applications/api"; -import ChannelServiceAPI from "../../../services/channels/provider"; import { ChannelVisibility } from "../../../services/channels/types"; import { Channel, ChannelMember } from "../../../services/channels/entities"; -import { MessageServiceAPI } from "../../../services/messages/api"; -import { Thread } from "../../../services/messages/entities/threads"; import { Message } from "../../../services/messages/entities/messages"; import { MessageWithReplies } from "../../../services/messages/types"; +import { formatCompany } from "../../../services/user/utils"; +import gr from "../../../services/global-resolver"; +import { formatUser } from "../../../utils/users"; /** * Merge command parameters. Check the builder definition below for more details. @@ -25,7 +22,7 @@ const services = [ "auth", "storage", "counter", - "pubsub", + "message-queue", "user", "files", "messages", @@ -58,9 +55,9 @@ const command: yargs.CommandModule = { }, handler: async argv => { const platform = await twake.run(services); - const userService = platform.getProvider("user"); + await gr.doInit(platform); - const company = await userService.companies.getCompany({ id: argv.id }); + const company = await gr.services.companies.getCompany({ id: argv.id }); if (!company) { return "No such company"; @@ -72,23 +69,23 @@ const command: yargs.CommandModule = { mkdirSync(output, { recursive: true }); //Company - console.log(`- Create company json file`); - writeFileSync(`${output}/company.json`, JSON.stringify(userService.formatCompany(company))); + console.log("- Create company json file"); + writeFileSync(`${output}/company.json`, JSON.stringify(formatCompany(company))); //Workspaces - console.log(`- Create workspaces json file`); - const workspaces = await userService.workspaces.getAllForCompany(company.id); + console.log("- Create workspaces json file"); + const workspaces = await gr.services.workspaces.getAllForCompany(company.id); writeFileSync(`${output}/workspaces.json`, JSON.stringify(workspaces)); //Users - console.log(`- Create users json file`); - let users = []; + console.log("- Create users json file"); + const users = []; for (const workspace of workspaces) { - let workspace_users = []; + const workspace_users = []; let workspaceUsers: WorkspaceUser[] = []; let pagination = new Pagination(); do { - const res = await userService.workspaces.getUsers( + const res = await gr.services.workspaces.getUsers( { workspaceId: workspace.id }, pagination, ); @@ -96,9 +93,9 @@ const command: yargs.CommandModule = { pagination = res.nextPage as Pagination; } while (pagination.page_token); for (const workspaceUser of workspaceUsers) { - const user = await userService.users.get({ id: workspaceUser.userId }); + const user = await gr.services.users.get({ id: workspaceUser.userId }); if (user) { - users.push(await userService.formatUser(user)); + users.push(await formatUser(user)); workspace_users.push({ ...workspaceUser, user }); } } @@ -111,9 +108,8 @@ const command: yargs.CommandModule = { writeFileSync(`${output}/users.json`, JSON.stringify(users)); //Applications - console.log(`- Create applications json file`); - const applicationService = platform.getProvider("applications"); - const applications = await applicationService.companyApplications.list( + console.log("- Create applications json file"); + const applications = await gr.services.applications.companyApps.list( new Pagination(), {}, { company: { id: company.id }, user: { id: "", server_request: true } }, @@ -121,25 +117,25 @@ const command: yargs.CommandModule = { writeFileSync(`${output}/applications.json`, JSON.stringify(applications)); //Channels - console.log(`- Create channels json file`); - let directChannels: Channel[] = []; + console.log("- Create channels json file"); + const directChannels: Channel[] = []; let allPublicChannels: Channel[] = []; - const channelService = platform.getProvider("channels"); let pagination = new Pagination(); do { - const page = await channelService.channels.getDirectChannelsInCompany(pagination, company.id); + const page = await gr.services.channels.channels.getDirectChannelsInCompany( + pagination, + company.id, + undefined, + ); for (const channel of page.getEntities()) { - const channelDetail = await channelService.channels.get( + const channelDetail = await gr.services.channels.channels.get( { company_id: channel.company_id, workspace_id: "direct", id: channel.id, }, - { - user: { id: "", server_request: true }, - workspace: { workspace_id: workspaces[0].id, company_id: company.id }, - }, + undefined, ); directChannels.push(channelDetail); } @@ -152,7 +148,7 @@ const command: yargs.CommandModule = { let publicChannels: Channel[] = []; pagination = new Pagination(); do { - const page = await channelService.channels.list( + const page = await gr.services.channels.channels.list( pagination, {}, { @@ -175,12 +171,12 @@ const command: yargs.CommandModule = { writeFileSync(`${output}/direct_channels.json`, JSON.stringify(directChannels)); //Channels users - console.log(`- Create channels users json file`); + console.log("- Create channels users json file"); for (const channel of [...allPublicChannels /*, ...directChannels*/]) { let members: ChannelMember[] = []; let pagination = new Pagination(); do { - const page = await channelService.members.list( + const page = await gr.services.channels.members.list( pagination, {}, { @@ -206,8 +202,7 @@ const command: yargs.CommandModule = { } //Messages - console.log(`- Create messages json file`); - const messageService = platform.getProvider("messages"); + console.log("- Create messages json file"); //Note: direct channels content is private and not needed for R&D for (const channel of [...allPublicChannels /*, ...directChannels*/]) { let threads: MessageWithReplies[] = []; @@ -215,7 +210,7 @@ const command: yargs.CommandModule = { let pagination = new Pagination(); try { do { - const page = await messageService.views.listChannel( + const page = await gr.services.messages.views.listChannel( pagination, { include_users: false, diff --git a/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts b/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts index 08ba851714..a4d1e77c0e 100644 --- a/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts +++ b/twake/backend/node/src/cli/cmds/generate_cmds/users-and-companies.ts @@ -8,9 +8,9 @@ import Company, { getInstance as getCompanyInstance, } from "../../../services/user/entities/company"; import CompanyUser from "../../../services/user/entities/company_user"; -import UserServiceAPI from "../../../services/user/api"; import twake from "../../../twake"; import User, { getInstance as getUserInstance } from "../../../services/user/entities/user"; +import gr from "../../../services/global-resolver"; type CLIArgs = { company: number; @@ -19,6 +19,13 @@ type CLIArgs = { }; const services = [ + "storage", + "counter", + "applications", + "statistics", + "auth", + "realtime", + "push", "platform-services", "user", "search", @@ -26,7 +33,7 @@ const services = [ "notifications", "database", "webserver", - "pubsub", + "message-queue", ]; // eslint-disable-next-line @typescript-eslint/ban-types @@ -57,21 +64,21 @@ const command: yargs.CommandModule<{}, CLIArgs> = { const nbUsersPerCompany = argv.user; const nbCompanies = argv.company; const platform = await twake.run(services); - const userService = platform.getProvider("user"); + await gr.doInit(platform); const companies = getCompanies(nbCompanies); const createUser = async (userInCompany: { user: User; company: Company; }): Promise => { console.log("Creating user", userInCompany); - const created = await userService.users.create(getUserInstance(userInCompany.user)); + const created = await gr.services.users.create(getUserInstance(userInCompany.user)); - return (await userService.companies.setUserRole(userInCompany.company.id, created.entity.id)) + return (await gr.services.companies.setUserRole(userInCompany.company.id, created.entity.id)) ?.entity; }; const createCompany = (company: Company) => { console.log("Creating company", company); - return userService.companies.createCompany(company); + return gr.services.companies.createCompany(company); }; const obsv$ = from(companies).pipe( diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/application.ts b/twake/backend/node/src/cli/cmds/migration_cmds/application.ts index 744d84f936..3d63f855db 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/application.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/application.ts @@ -7,12 +7,12 @@ import PhpApplication, { DepreciatedDisplayConfiguration, TYPE as phpTYPE, } from "./php-application/php-application-entity"; -import { Pagination } from "../../../core/platform/framework/api/crud-service"; +import { ExecutionContext, Pagination } from "../../../core/platform/framework/api/crud-service"; import Application, { + ApplicationPublication, TYPE, - getInstance, } from "../../../services/applications/entities/application"; -import _ from "lodash"; +import gr from "../../../services/global-resolver"; type Options = { onlyApplication?: string; @@ -32,18 +32,22 @@ class ApplicationMigrator { let page: Pagination = { limitStr: "100" }; do { - const applicationListResult = await phpRepository.find({}, { pagination: page }); + const applicationListResult = await phpRepository.find({}, { pagination: page }, undefined); page = applicationListResult.nextPage as Pagination; for (const application of applicationListResult.getEntities()) { if ( - !(await repository.findOne({ - id: application.id, - })) || + !(await repository.findOne( + { + id: application.id, + }, + {}, + undefined, + )) || options.replaceExisting ) { const newApplication = importDepreciatedFields(application); - await repository.save(newApplication); + await repository.save(newApplication, undefined); } } } while (page.page_token); @@ -59,7 +63,7 @@ const services = [ "channels", "database", "webserver", - "pubsub", + "message-queue", "applications", "console", "auth", @@ -86,6 +90,7 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Migrating php applications - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new ApplicationMigrator(platform); const onlyApplication = argv.onlyApplication as string | null; @@ -124,32 +129,44 @@ export const importDepreciatedFields = (application: PhpApplication): Applicatio } if (newApplication.publication?.published === undefined) { - //@ts-ignore - newApplication.publication = newApplication.publication || {}; + newApplication.publication = newApplication.publication || { + published: false, + requested: false, + }; newApplication.publication.published = application.depreciated_is_available_to_public; newApplication.publication.requested = application.depreciated_public && !application.depreciated_twake_team_validation; } if (!newApplication.stats?.version) { - //@ts-ignore - newApplication.stats = newApplication.stats || {}; + newApplication.stats = newApplication.stats || { + created_at: null, + updated_at: null, + version: null, + }; newApplication.stats.version = 1; - newApplication.stats.createdAt = Date.now(); - newApplication.stats.updatedAt = Date.now(); + newApplication.stats.created_at = Date.now(); + newApplication.stats.updated_at = Date.now(); } - if (!newApplication.api?.privateKey) { - //@ts-ignore - newApplication.api = newApplication.api || {}; - newApplication.api.hooksUrl = application.depreciated_api_events_url; - newApplication.api.allowedIps = application.depreciated_api_allowed_ip; - newApplication.api.privateKey = application.depreciated_api_private_key; + if (!newApplication.api?.private_key) { + newApplication.api = newApplication.api || { + hooks_url: null, + allowed_ips: null, + private_key: null, + }; + newApplication.api.hooks_url = application.depreciated_api_events_url; + newApplication.api.allowed_ips = application.depreciated_api_allowed_ip; + newApplication.api.private_key = application.depreciated_api_private_key; } if (newApplication.access?.write === undefined) { - //@ts-ignore - newApplication.access = newApplication.access || {}; + newApplication.access = newApplication.access || { + read: null, + write: null, + delete: null, + hooks: null, + }; try { newApplication.access.write = JSON.parse(application.depreciated_capabilities || "[]") || []; newApplication.access.delete = JSON.parse(application.depreciated_capabilities || "[]") || []; @@ -197,9 +214,9 @@ export const importDepreciatedDisplayFields = ( : undefined; display.twake.configuration = []; - if (depreciatedDisplay.configuration?.can_configure_in_workspace) + if (depreciatedDisplay?.configuration?.can_configure_in_workspace) display.twake.configuration.push("global"); - if (depreciatedDisplay.configuration?.can_configure_in_channel) + if (depreciatedDisplay?.configuration?.can_configure_in_channel) display.twake.configuration.push("channel"); display.twake.direct = depreciatedDisplay?.member_app diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/channel-member-read-cursors.ts b/twake/backend/node/src/cli/cmds/migration_cmds/channel-member-read-cursors.ts new file mode 100644 index 0000000000..02026be60c --- /dev/null +++ b/twake/backend/node/src/cli/cmds/migration_cmds/channel-member-read-cursors.ts @@ -0,0 +1,173 @@ +import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; +import { TwakePlatform } from "../../../core/platform/platform"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { ChannelMember, ChannelMemberReadCursors } from "../../../services/channels/entities"; +import { + ExecutionContext, + Paginable, + Pagination, +} from "../../../core/platform/framework/api/crud-service"; +import gr from "../../../services/global-resolver"; +import yargs from "yargs"; +import ora from "ora"; +import twake from "../../../twake"; + +class ChannelMemberReadCursorsMigrator { + readSectionRepository: Repository; + database: DatabaseServiceAPI; + + constructor(readonly platform: TwakePlatform) { + this.database = this.platform.getProvider("database"); + } + + public async run(options = {}, context?: ExecutionContext): Promise { + const companyPagination: Paginable = new Pagination(null, "100"); + const companies = await gr.services.companies.getCompanies(companyPagination); + + context.user.server_request = true; + + for (const company of companies.getEntities()) { + const { id: CompanyId } = company; + + const workspaces = await gr.services.workspaces.getAllForCompany(CompanyId); + const workspaceIds = [...workspaces.map(({ id }) => id), "direct"]; + + for (const workspaceId of workspaceIds) { + const channels = await gr.services.channels.channels.getAllChannelsInWorkspace( + CompanyId, + workspaceId, + ); + + for (const channel of channels) { + const { id: channelId } = channel; + const membersPagination: Pagination = new Pagination(null, "100"); + const threadsPagination: Pagination = new Pagination(null, "1"); + let members: ChannelMember[]; + + try { + const membersList = await gr.services.channels.members.list( + membersPagination, + {}, + { + ...context, + channel: { + company_id: CompanyId, + id: channelId, + workspace_id: workspaceId, + }, + }, + ); + members = membersList.getEntities(); + } catch (error) { + continue; + } + + let lastMessage = await gr.services.messages.views.listChannel( + threadsPagination, + {}, + { + ...context, + channel: { + company_id: CompanyId, + id: channelId, + workspace_id: workspaceId, + }, + user: { + id: null, + }, + }, + ); + + const firstMessage = await gr.services.messages.views.listChannel( + { + ...threadsPagination, + reversed: true, + }, + {}, + { + ...context, + channel: { + company_id: CompanyId, + id: channelId, + workspace_id: workspaceId, + }, + user: { + id: null, + }, + }, + ); + + if (!firstMessage.getEntities().length) { + continue; + } + + if (!lastMessage.getEntities().length) { + lastMessage = firstMessage; + } + + const firstMessageId = firstMessage.getEntities()[0].id; + const lastMessageId = lastMessage.getEntities()[0].id; + + if (!firstMessageId) { + continue; + } else { + for (const member of members) { + await gr.services.channels.members.setChannelMemberReadSections( + { + start: firstMessageId, + end: lastMessageId, + }, + { + ...context, + channel_id: channelId, + workspace_id: workspaceId, + company: { + id: CompanyId, + }, + user: { + id: member.user_id, + }, + }, + ); + } + } + } + } + } + } +} + +const services = [ + "search", + "database", + "webserver", + "auth", + "counter", + "cron", + "message-queue", + "push", + "realtime", + "storage", + "tracker", + "websocket", + "email-pusher", +]; + +const command: yargs.CommandModule = { + command: "channel-member-read-cursor-repair", + describe: "fixes the channel members read cursors for old messages", + builder: {}, + + handler: async () => { + const spinner = ora({ text: "Fixing channel members read cursors" }).start(); + const platform = await twake.run(services); + await gr.doInit(platform); + const migrator = new ChannelMemberReadCursorsMigrator(platform); + + await migrator.run({}); + + return spinner.stop(); + }, +}; + +export default command; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/devices.ts b/twake/backend/node/src/cli/cmds/migration_cmds/devices.ts index fd4fae3bbc..cb5ffab13f 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/devices.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/devices.ts @@ -8,6 +8,7 @@ import { Pagination } from "../../../core/platform/framework/api/crud-service"; import Device, { TYPE, getInstance } from "../../../services/user/entities/device"; import User, { TYPE as userTYPE } from "../../../services/user/entities/user"; import _ from "lodash"; +import gr from "../../../services/global-resolver"; type Options = { replaceExisting?: boolean; @@ -29,23 +30,26 @@ class DeviceMigrator { let page: Pagination = { limitStr: "100" }; // For each devices do { - const deviceListResult = await phpRepository.find({}, { pagination: page }); + const deviceListResult = await phpRepository.find({}, { pagination: page }, undefined); page = deviceListResult.nextPage as Pagination; for (const device of deviceListResult.getEntities()) { - if (!(await repository.findOne({ id: device.value })) || options.replaceExisting) { + if ( + !(await repository.findOne({ id: device.value }, {}, undefined)) || + options.replaceExisting + ) { if (device.type === "FCM" || device.type === "fcm") { const newDevice = new Device(); newDevice.id = device.value; newDevice.type = "FCM"; newDevice.user_id = device.user_id; newDevice.version = device.version; - await repository.save(newDevice); + await repository.save(newDevice, undefined); - const user = await userRepository.findOne({ id: device.user_id }); + const user = await userRepository.findOne({ id: device.user_id }, {}, undefined); if (user) { user.devices = _.uniq([...(user.devices || []), newDevice.id]); - await userRepository.save(user); + await userRepository.save(user, undefined); } } } @@ -63,7 +67,7 @@ const services = [ "channels", "database", "webserver", - "pubsub", + "message-queue", "workspaces", "console", "auth", @@ -83,6 +87,7 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Migrating php devices - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new DeviceMigrator(platform); const replaceExisting = (argv.replaceExisting || false) as boolean; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/message-channel-repair.ts b/twake/backend/node/src/cli/cmds/migration_cmds/message-channel-repair.ts index 1587fb6904..c0e35e1676 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/message-channel-repair.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/message-channel-repair.ts @@ -3,6 +3,7 @@ import twake from "../../../twake"; import ora from "ora"; import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; import { TwakePlatform } from "../../../core/platform/platform"; +import gr from "../../../services/global-resolver"; type Options = { from?: string; @@ -33,7 +34,7 @@ const services = [ "channels", "database", "webserver", - "pubsub", + "message-queue", "messages", ]; @@ -71,6 +72,7 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Fixing messages references - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new MessageReferenceRepair(platform); const from = argv.from as string | null; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/message-files-cache.ts b/twake/backend/node/src/cli/cmds/migration_cmds/message-files-cache.ts new file mode 100644 index 0000000000..c0003a551b --- /dev/null +++ b/twake/backend/node/src/cli/cmds/migration_cmds/message-files-cache.ts @@ -0,0 +1,189 @@ +import yargs from "yargs"; +import twake from "../../../twake"; +import ora from "ora"; +import { TwakePlatform } from "../../../core/platform/platform"; +import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; +import { + ExecutionContext, + Paginable, + Pagination, +} from "../../../core/platform/framework/api/crud-service"; +import gr from "../../../services/global-resolver"; +import { getInstance, MessageFileRef } from "../../../services/messages/entities/message-file-refs"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import uuid from "node-uuid"; +import { MessageFile } from "../../../services/messages/entities/message-files"; +import { ThreadExecutionContext } from "../../../services/messages/types"; + +type Options = {}; + +class MessageFilesCacheMigrator { + database: DatabaseServiceAPI; + repository: Repository; + messageFileRepository: Repository; + + constructor(readonly platform: TwakePlatform) { + this.database = this.platform.getProvider("database"); + } + + public async run(options: Options = {}, context?: ExecutionContext): Promise { + this.repository = await gr.database.getRepository( + "message_file_refs", + MessageFileRef, + ); + this.messageFileRepository = await gr.database.getRepository( + "message_files", + MessageFile, + ); + + let count = 0; + + let companyPagination: Paginable = new Pagination(null, "100"); + do { + const companyList = await gr.services.companies.getCompanies(companyPagination); + companyPagination = companyList.nextPage; + + for (const company of companyList.getEntities()) { + const companyId: string = company.id; + const workspaceList = await gr.services.workspaces.getAllForCompany(companyId); + + for (const workspaceId of [...workspaceList.map(w => w.id), "direct"]) { + const channelsList = await gr.services.channels.channels.getAllChannelsInWorkspace( + companyId, + workspaceId, + context, + ); + + for (const channel of channelsList) { + const channelId = channel.id; + + let threadPagination: Paginable = new Pagination(null, "100"); + do { + const threadList = await gr.services.messages.views.listChannel( + threadPagination, + {}, + { + channel: { + company_id: companyId, + workspace_id: workspaceId, + id: channelId, + }, + user: { id: null }, + }, + ); + + for (const thread of threadList.getEntities()) { + let messagesPagination: Paginable = new Pagination(null, "100"); + do { + const messagesList = await gr.services.messages.messages.list( + messagesPagination, + {}, + { + thread: { id: thread.id }, + company: { id: companyId }, + workspace: { id: workspaceId }, + channel: { id: channelId }, + user: { id: null }, + } as ThreadExecutionContext, + ); + messagesPagination = messagesList.nextPage; + messagesPagination.page_token = messagesList.getEntities()[0]?.id; + + for (const message of messagesList.getEntities()) { + if (message.files && message.files.length > 0) { + for (const _messageFile of message.files) { + count++; + try { + const messageFile = await this.messageFileRepository.findOne( + { + message_id: message.id, + id: _messageFile.id, + }, + {}, + undefined, + ); + + if (messageFile) { + console.log(messageFile.metadata.name); + + //Update user uploads + const fileRef = getInstance({ + target_type: "user_upload", + target_id: message.user_id, + id: uuid.v1({ msecs: message.created_at }), + created_at: message.created_at, + company_id: companyId, + workspace_id: workspaceId, + channel_id: channelId, + thread_id: message.thread_id, + message_id: message.id, + message_file_id: messageFile.id, + file_id: messageFile.metadata.external_id, + }); + await this.repository.save(fileRef, undefined); + + //Update messageFileRepository + + messageFile.cache = { + company_id: companyId, + workspace_id: workspaceId, + channel_id: channelId, + user_id: message.user_id, + }; + messageFile.thread_id = message.thread_id; + + await this.messageFileRepository.save(messageFile, undefined); + } + } catch (e) {} + } + } + } + } while (messagesPagination.page_token); + } + + threadPagination = threadList.nextPage; + threadPagination.page_token = + threadPagination.page_token && + threadList.getEntities()?.[threadList.getEntities().length - 1]?.thread_id; + } while (false); // && threadPagination.page_token && threadList.getEntities().length > 50); + } + } + } + console.log("updated messages: ", count); + } while (companyPagination.page_token); + } +} + +const services = [ + "search", + "database", + "webserver", + "auth", + "counter", + "cron", + "message-queue", + "push", + "realtime", + "storage", + "tracker", + "websocket", +]; + +const command: yargs.CommandModule = { + command: "message-files-cache", + describe: "command that allow you to fix cache for each message-file refs", + builder: {}, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + handler: async argv => { + const spinner = ora({ text: "Migrating messages - " }).start(); + const platform = await twake.run(services); + await gr.doInit(platform); + const migrator = new MessageFilesCacheMigrator(platform); + + await migrator.run({}); + + return spinner.stop(); + }, +}; + +export default command; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/message.ts b/twake/backend/node/src/cli/cmds/migration_cmds/message.ts index ea6f8d56dd..b2814cf963 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/message.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/message.ts @@ -2,6 +2,7 @@ import yargs from "yargs"; import twake from "../../../twake"; import ora from "ora"; import MessageMigrator from "./php-message/message-migrator-service"; +import gr from "../../../services/global-resolver"; const services = [ "storage", @@ -12,7 +13,7 @@ const services = [ "channels", "database", "webserver", - "pubsub", + "message-queue", "messages", "statistics", ]; @@ -62,6 +63,7 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Migrating php messages - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new MessageMigrator(platform); const from = argv.from as string | null; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/messages-files-medias-separation.ts b/twake/backend/node/src/cli/cmds/migration_cmds/messages-files-medias-separation.ts new file mode 100644 index 0000000000..13d180276d --- /dev/null +++ b/twake/backend/node/src/cli/cmds/migration_cmds/messages-files-medias-separation.ts @@ -0,0 +1,125 @@ +import yargs from "yargs"; +import twake from "../../../twake"; +import ora from "ora"; +import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; +import { TwakePlatform } from "../../../core/platform/platform"; +import gr from "../../../services/global-resolver"; +import { MessageFileRef } from "../../../services/messages/entities/message-file-refs"; +import { Paginable } from "../../../core/platform/framework/api/crud-service"; +import { Pagination } from "../../../core/platform/framework/api/crud-service"; +import { fileIsMedia } from "../../../services/files/utils"; +import { MessageFile } from "../../../services/messages/entities/message-files"; +import _ from "lodash"; + +type Options = {}; + +class MessageReferenceRepair { + database: DatabaseServiceAPI; + + constructor(readonly platform: TwakePlatform) { + this.database = this.platform.getProvider("database"); + } + + public async run(options: Options = {}): Promise { + const repository = await gr.database.getRepository( + "message_file_refs", + MessageFileRef, + ); + const repositoryMessageFile = await gr.database.getRepository( + "message_files", + MessageFile, + ); + + let count = 0; + + let companyPagination: Paginable = new Pagination(null, "100"); + do { + const companyList = await gr.services.companies.getCompanies(companyPagination); + companyPagination = companyList.nextPage; + + for (const company of companyList.getEntities()) { + const companyId: string = company.id; + const workspaceList = await gr.services.workspaces.getAllForCompany(companyId); + + for (const workspaceId of [...workspaceList.map(w => w.id), "direct"]) { + const channelsList = await gr.services.channels.channels.getAllChannelsInWorkspace( + companyId, + workspaceId, + ); + + for (const channel of channelsList) { + const channelId = channel.id; + let filePagination: Pagination = new Pagination(null, "100"); + + do { + const items = await repository.find( + { + target_type: "channel", + target_id: channelId, + company_id: companyId, + }, + { pagination: filePagination }, + ); + + for (const item of items.getEntities()) { + try { + const msgFile = await repositoryMessageFile.findOne({ + message_id: item.message_id, + id: item.message_file_id, + }); + if (msgFile) { + count++; + const isMedia = fileIsMedia(msgFile); + const ref = _.cloneDeep(item); + ref.target_type = isMedia ? "channel_media" : "channel_file"; + await repository.save(ref); + } + } catch (e) { + console.log("Error", e); + } + } + + filePagination = new Pagination(items.nextPage.page_token, "100"); + } while (filePagination.page_token); + } + } + } + + console.log("updated files refs: ", count); + } while (companyPagination.page_token); + } +} + +const services = [ + "search", + "database", + "webserver", + "auth", + "counter", + "cron", + "message-queue", + "push", + "realtime", + "storage", + "tracker", + "websocket", +]; + +const command: yargs.CommandModule = { + command: "messages-files-medias-separation", + describe: "command to separate medias and files in messages-files channels refs", + builder: {}, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + handler: async argv => { + const spinner = ora({ text: "Fixing messages references - " }).start(); + const platform = await twake.run(services); + await gr.doInit(platform); + const migrator = new MessageReferenceRepair(platform); + + await migrator.run({}); + + return spinner.stop(); + }, +}; + +export default command; diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/message-migrator-service.ts b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/message-migrator-service.ts index 561c6869a6..310fa14146 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/message-migrator-service.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/message-migrator-service.ts @@ -1,13 +1,9 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; import { PhpMessagesService } from "./php-message-service"; -import UserServiceAPI from "../../../../services/user/api"; -import ChannelServiceAPI from "../../../../services/channels/provider"; import { convertUuidV4ToV1 } from "./utils"; import Company from "../../../../services/user/entities/company"; import { Pagination } from "../../../../core/platform/framework/api/crud-service"; import { PhpMessage } from "./php-message-entity"; import { TwakePlatform } from "../../../../core/platform/platform"; -import { MessageServiceAPI } from "../../../../services/messages/api"; import { Message, MessageEdited, @@ -19,6 +15,7 @@ import { MessageChannelRef } from "../../../../services/messages/entities/messag import { ParticipantObject, Thread } from "../../../../services/messages/entities/threads"; import { Block } from "../../../../services/messages/blocks-types"; import { WorkspaceExecutionContext } from "../../../../services/workspaces/types"; +import gr from "../../../../services/global-resolver"; type MigratedChannel = { id: string; @@ -37,29 +34,22 @@ type Options = { dryRun?: boolean; }; class MessageMigrator { - private database: DatabaseServiceAPI; - private userService: UserServiceAPI; - private channelService: ChannelServiceAPI; private phpMessageService: PhpMessagesService; - private nodeMessageService: MessageServiceAPI; - private migratedMessages: number = 0; + private migratedMessages = 0; private options: Options = {}; constructor(readonly platform: TwakePlatform) { - this.database = this.platform.getProvider("database"); - this.userService = this.platform.getProvider("user"); - this.channelService = this.platform.getProvider("channels"); - this.phpMessageService = new PhpMessagesService(this.database); - this.nodeMessageService = this.platform.getProvider("messages"); + this.phpMessageService = new PhpMessagesService(); } public async run(options: Options = {}): Promise { + await gr.doInit(this.platform); this.options = options; await this.phpMessageService.init(); if (this.options.onlyCompany) { - const company = await this.userService.companies.getCompany({ id: options.onlyCompany }); + const company = await gr.services.companies.getCompany({ id: options.onlyCompany }); await this.migrateCompanyMessages(company); } else { let waitForCompany = false; @@ -71,7 +61,7 @@ class MessageMigrator { let page: Pagination = { limitStr: "100" }; // For each companies find workspaces do { - const companyListResult = await this.userService.companies.getCompanies(page); + const companyListResult = await gr.services.companies.getCompanies(page); page = companyListResult.nextPage as Pagination; for (const company of companyListResult.getEntities()) { @@ -111,10 +101,11 @@ class MessageMigrator { * Set all direct messages in company and set them to channelPhpMessages */ private async migrateCompanyDirectMessages(company: Company) { + await gr.doInit(this.platform); let pageDirectChannels: Pagination = { limitStr: "100" }; // For each directChannels find messages do { - const directChannelsInCompanyResult = await this.channelService.channels.list( + const directChannelsInCompanyResult = await gr.services.channels.channels.list( pageDirectChannels, {}, { @@ -142,9 +133,11 @@ class MessageMigrator { * Set all messages in company and set them to channelPhpMessages */ private async migrateCompanyChannelsMessages(company: Company) { + await gr.doInit(this.platform); + // Get all workspaces in company const workspacesInCompany = ( - await this.userService.workspaces.list({ limitStr: "" }, {}, { + await gr.services.workspaces.list({ limitStr: "" }, {}, { user: { id: null, server_request: true, @@ -162,7 +155,7 @@ class MessageMigrator { // Get all channels in workspace let pageChannels: Pagination = { limitStr: "1" }; do { - const channelsInWorkspace = await this.channelService.channels.list( + const channelsInWorkspace = await gr.services.channels.channels.list( pageChannels, {}, { @@ -235,12 +228,12 @@ class MessageMigrator { if (!message.id) { return; } - + await gr.doInit(this.platform); //Create thread first if not exists const threadId = message.parent_message_id || message.id; if (this.options.ignoreExisting) { - const msg = await this.nodeMessageService.messages.get({ + const msg = await gr.services.messages.messages.get({ thread_id: threadId, id: message.id, }); @@ -271,11 +264,12 @@ class MessageMigrator { } private async migrateChannelsMessagesBackToPhp(company: Company, channel: MigratedChannel) { - const channelRefRepository = await this.database.getRepository( + await gr.doInit(this.platform); + const channelRefRepository = await gr.database.getRepository( "message_channel_refs", MessageChannelRef, ); - const messageRepository = await this.database.getRepository("messages", Message); + const messageRepository = await gr.database.getRepository("messages", Message); //This function will migrate all messages in a channel let pageMessages: Pagination = { limitStr: "100" }; @@ -287,12 +281,17 @@ class MessageMigrator { channel_id: channel.id, }, { pagination: pageMessages }, + undefined, ); for (const messageRef of messages.getEntities()) { - const messages = await messageRepository.find({ - thread_id: messageRef.thread_id, - }); + const messages = await messageRepository.find( + { + thread_id: messageRef.thread_id, + }, + {}, + undefined, + ); for (const message of messages.getEntities()) { const uuidv1_channel_id = @@ -359,7 +358,7 @@ class MessageMigrator { }; if (!this.options.dryRun) { - await this.phpMessageService.repository.save(newPhpMessage); + await this.phpMessageService.repository.save(newPhpMessage, undefined); } this.migratedMessages++; @@ -407,7 +406,7 @@ class MessageMigrator { } // Create nodeThread - return await this.nodeMessageService.threads.save( + return await gr.services.messages.threads.save( thread, {}, { user: { id: null, server_request: true }, company }, @@ -544,7 +543,7 @@ class MessageMigrator { } // Create nodeMessage then add it to thread - return await this.nodeMessageService.messages.save( + return await gr.services.messages.messages.save( nodeMessage, { enforceViewPropagation: true, diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/php-message-service.ts b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/php-message-service.ts index 5acebd0200..5995a24f1b 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/php-message-service.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/php-message-service.ts @@ -1,15 +1,15 @@ import { DeleteResult, + ExecutionContext, ListResult, Pagination, } from "../../../../core/platform/framework/api/crud-service"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; import Repository, { FindFilter, } from "../../../../core/platform/services/database/services/orm/repository/repository"; import { PhpMessagesServiceAPI } from "./types"; import { PhpMessage, PhpMessagePrimaryKey } from "./php-message-entity"; -import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; +import gr from "../../../../services/global-resolver"; export interface PhpMessageExecutionContext extends ExecutionContext { channel_id: string; @@ -21,10 +21,8 @@ export class PhpMessagesService implements PhpMessagesServiceAPI { version: "1"; public repository: Repository; - constructor(private database: DatabaseServiceAPI) {} - async init(): Promise { - this.repository = await this.database.getRepository("message", PhpMessage); + this.repository = await gr.database.getRepository("message", PhpMessage); return this; } @@ -33,7 +31,7 @@ export class PhpMessagesService implements PhpMessagesServiceAPI { pk.channel_id = `${pk.channel_id}`; pk.channel_id.substring(0, 14) + "1" + pk.channel_id.substring(14 + 1); } - return this.repository.findOne(pk); + return this.repository.findOne(pk, {}, undefined); } // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -55,7 +53,7 @@ export class PhpMessagesService implements PhpMessagesServiceAPI { //id: context.id, }; - const list = await this.repository.find(findFilter, { pagination }); + const list = await this.repository.find(findFilter, { pagination }, undefined); return list; } } diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/types.ts b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/types.ts index 8ac1e899b4..067e7abce5 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/php-message/types.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/php-message/types.ts @@ -1,14 +1,3 @@ -import { TwakeServiceProvider, Initializable } from "../../../../core/platform/framework"; -import { - CRUDService, - ExecutionContext, -} from "../../../../core/platform/framework/api/crud-service"; -import { - PhpMessage, - PhpMessagePrimaryKey, -} from "./php-message-entity"; +import { Initializable, TwakeServiceProvider } from "../../../../core/platform/framework"; -export interface PhpMessagesServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService {} +export interface PhpMessagesServiceAPI extends TwakeServiceProvider, Initializable {} diff --git a/twake/backend/node/src/cli/cmds/migration_cmds/workspace.ts b/twake/backend/node/src/cli/cmds/migration_cmds/workspace.ts index c2ff6bd860..dfb6fce985 100644 --- a/twake/backend/node/src/cli/cmds/migration_cmds/workspace.ts +++ b/twake/backend/node/src/cli/cmds/migration_cmds/workspace.ts @@ -8,6 +8,7 @@ import { Pagination } from "../../../core/platform/framework/api/crud-service"; import Workspace, { TYPE, getInstance } from "../../../services/workspaces/entities/workspace"; import _ from "lodash"; import { logger } from "../../../core/platform/framework"; +import gr from "../../../services/global-resolver"; type Options = { from?: string; @@ -36,7 +37,7 @@ class WorkspaceMigrator { let page: Pagination = { limitStr: "100" }; // For each companies find workspaces do { - const workspaceListResult = await phpRepository.find({}, { pagination: page }); + const workspaceListResult = await phpRepository.find({}, { pagination: page }, undefined); page = workspaceListResult.nextPage as Pagination; for (const workspace of workspaceListResult.getEntities()) { @@ -50,7 +51,11 @@ class WorkspaceMigrator { options.onlyCompany == `${workspace.group_id}` ) { if ( - !(await repository.findOne({ company_id: workspace.group_id, id: workspace.id })) || + !(await repository.findOne( + { company_id: workspace.group_id, id: workspace.id }, + {}, + undefined, + )) || options.replaceExisting ) { const newWorkspace = getInstance( @@ -68,7 +73,7 @@ class WorkspaceMigrator { ), ); newWorkspace.company_id = workspace.group_id; - await repository.save(newWorkspace); + await repository.save(newWorkspace, undefined); } } } @@ -87,7 +92,7 @@ const services = [ "channels", "database", "webserver", - "pubsub", + "message-queue", "workspaces", "console", "auth", @@ -122,6 +127,7 @@ const command: yargs.CommandModule = { handler: async argv => { const spinner = ora({ text: "Migrating php worskpaces - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new WorkspaceMigrator(platform); const from = argv.from as string | null; diff --git a/twake/backend/node/src/cli/cmds/search_cmds/index_all.ts b/twake/backend/node/src/cli/cmds/search_cmds/index_all.ts index 39cbeebdd4..a68728305f 100644 --- a/twake/backend/node/src/cli/cmds/search_cmds/index_all.ts +++ b/twake/backend/node/src/cli/cmds/search_cmds/index_all.ts @@ -4,16 +4,25 @@ import ora from "ora"; import { TwakePlatform } from "../../../core/platform/platform"; import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; import { Pagination } from "../../../core/platform/framework/api/crud-service"; -import _ from "lodash"; + import User, { TYPE as UserTYPE } from "../../../services/user/entities/user"; +import { Channel } from "../../../services/channels/entities"; import Application, { TYPE as ApplicationTYPE, } from "../../../services/applications/entities/application"; import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; import { SearchServiceAPI } from "../../../core/platform/services/search/api"; +import CompanyUser, { TYPE as CompanyUserTYPE } from "../../../services/user/entities/company_user"; +import { Message, TYPE as MessageTYPE } from "../../../services/messages/entities/messages"; +import gr from "../../../services/global-resolver"; +import { + MessageFile, + TYPE as MessageFileTYPE, +} from "../../../services/messages/entities/message-files"; type Options = { repository?: string; + repairEntities?: boolean; }; class SearchIndexAll { @@ -27,7 +36,13 @@ class SearchIndexAll { public async run(options: Options = {}): Promise { const repositories: Map> = new Map(); + repositories.set("messages", await this.database.getRepository(MessageTYPE, Message)); + repositories.set( + "message_files", + await this.database.getRepository(MessageFileTYPE, MessageFile), + ); repositories.set("users", await this.database.getRepository(UserTYPE, User)); + repositories.set("channels", await this.database.getRepository("channels", Channel)); repositories.set( "applications", await this.database.getRepository(ApplicationTYPE, Application), @@ -35,22 +50,76 @@ class SearchIndexAll { const repository = repositories.get(options.repository); if (!repository) { - throw `No such repository ready for indexation, available are: users, applications`; + throw ( + "No such repository ready for indexation, available are: " + + Array.from(repositories.keys()).join(", ") + ); } - // Get all companies + // Complete user with companies in cache + if (options.repository === "users" && options.repairEntities) { + console.log("Complete user with companies in cache"); + const companiesUsersRepository = await this.database.getRepository( + CompanyUserTYPE, + CompanyUser, + ); + const userRepository = await this.database.getRepository(UserTYPE, User); + let page: Pagination = { limitStr: "100" }; + // For each rows + do { + const list = await userRepository.find({}, { pagination: page }, undefined); + + for (const user of list.getEntities()) { + const companies = await companiesUsersRepository.find( + { user_id: user.id }, + {}, + undefined, + ); + + user.cache ||= { companies: [] }; + user.cache.companies = companies.getEntities().map(company => company.group_id); + await repositories.get("users").save(user, undefined); + } + + page = list.nextPage as Pagination; + await new Promise(r => setTimeout(r, 200)); + } while (page.page_token); + } + + console.log("Start indexing..."); + let count = 0; + // Get all items let page: Pagination = { limitStr: "100" }; - // For each devices do { - const list = await repository.find({}, { pagination: page }); + console.log("Indexed " + count + " items..."); + const list = await repository.find({}, { pagination: page }, undefined); page = list.nextPage as Pagination; await this.search.upsert(list.getEntities()); + count += list.getEntities().length; await new Promise(r => setTimeout(r, 200)); } while (page.page_token); + + console.log("Emptying flush (10s)..."); + await new Promise(r => setTimeout(r, 10000)); + + console.log("Done!"); } } -const services = ["search", "database", "webserver"]; +const services = [ + "search", + "database", + "webserver", + "auth", + "counter", + "cron", + "message-queue", + "push", + "realtime", + "storage", + "tracker", + "websocket", +]; const command: yargs.CommandModule = { command: "index", @@ -61,11 +130,17 @@ const command: yargs.CommandModule = { type: "string", description: "Choose a repository to reindex", }, + repairEntities: { + default: false, + type: "boolean", + description: "Choose to repair entities too when possible", + }, }, // eslint-disable-next-line @typescript-eslint/no-unused-vars handler: async argv => { const spinner = ora({ text: "Reindex repository - " }).start(); const platform = await twake.run(services); + await gr.doInit(platform); const migrator = new SearchIndexAll(platform); const repository = (argv.repository || "") as string; diff --git a/twake/backend/node/src/cli/cmds/users_cmds/remove.ts b/twake/backend/node/src/cli/cmds/users_cmds/remove.ts index 4fa4c79d12..f93043095b 100644 --- a/twake/backend/node/src/cli/cmds/users_cmds/remove.ts +++ b/twake/backend/node/src/cli/cmds/users_cmds/remove.ts @@ -1,9 +1,9 @@ import yargs from "yargs"; import ora from "ora"; import twake from "../../../twake"; -import UserServiceAPI from "../../../services/user/api"; -import { getInstance as getUserInstance } from "../../../services/user/entities/user"; import Table from "cli-table"; +import { exit } from "process"; +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. @@ -15,13 +15,17 @@ type CLIArgs = { const services = [ "storage", "counter", - "pubsub", + "message-queue", "platform-services", "user", "search", "database", "webserver", "statistics", + "applications", + "auth", + "realtime", + "websocket", ]; const command: yargs.CommandModule = { @@ -46,9 +50,9 @@ const command: yargs.CommandModule = { const spinner = ora({ text: "Retrieving user" }).start(); const platform = await twake.run(services); - const userService = platform.getProvider("user"); + await gr.doInit(platform); - const user = await userService.users.get({ id: argv.id }); + const user = await gr.services.users.get({ id: argv.id }); if (!user) { console.error("Error: You need to provide User ID"); @@ -59,20 +63,22 @@ const command: yargs.CommandModule = { // Table before tableBefore.push([user.id, user.username_canonical, user.deleted]); - await userService.users.anonymizeAndDelete( + await gr.services.users.anonymizeAndDelete( { id: user.id }, { user: { id: user.id, server_request: true }, }, ); - const finalUser = await userService.users.get(getUserInstance({ id: argv.id })); + const finalUser = await gr.services.users.get({ id: argv.id }); // Table after tableAfter.push([finalUser.id, finalUser.username_canonical, finalUser.deleted]); spinner.stop(); } + + exit(); }, }; diff --git a/twake/backend/node/src/cli/cmds/workspace_cmds/list.ts b/twake/backend/node/src/cli/cmds/workspace_cmds/list.ts index 909d244fc1..910f1f4cfa 100644 --- a/twake/backend/node/src/cli/cmds/workspace_cmds/list.ts +++ b/twake/backend/node/src/cli/cmds/workspace_cmds/list.ts @@ -2,8 +2,7 @@ import yargs from "yargs"; import ora from "ora"; import Table from "cli-table"; import twake from "../../../twake"; -import UserServiceAPI from "../../../services/user/api"; - +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. */ @@ -19,7 +18,7 @@ const services = [ "notifications", "database", "webserver", - "pubsub", + "message-queue", ]; const command: yargs.CommandModule = { @@ -36,8 +35,8 @@ const command: yargs.CommandModule = { const table = new Table({ head: ["ID", "Name"], colWidths: [40, 50] }); const spinner = ora({ text: "List Twake workspaces" }).start(); const platform = await twake.run(services); - const userService = platform.getProvider("user"); - const workspaces = await userService.workspaces.list({ limitStr: argv.size }); + await gr.doInit(platform); + const workspaces = await gr.services.workspaces.list({ limitStr: argv.size }); spinner.stop(); workspaces.getEntities().forEach(ws => table.push([ws.id, ws.name])); diff --git a/twake/backend/node/src/cli/cmds/workspace_cmds/user.ts b/twake/backend/node/src/cli/cmds/workspace_cmds/user.ts index 036f49d878..bc5b139bf5 100644 --- a/twake/backend/node/src/cli/cmds/workspace_cmds/user.ts +++ b/twake/backend/node/src/cli/cmds/workspace_cmds/user.ts @@ -2,8 +2,7 @@ import yargs from "yargs"; import ora from "ora"; import Table from "cli-table"; import twake from "../../../twake"; -import UserServiceAPI from "../../../services/user/api"; - +import gr from "../../../services/global-resolver"; /** * Merge command parameters. Check the builder definition below for more details. */ @@ -19,7 +18,7 @@ const services = [ "notifications", "database", "webserver", - "pubsub", + "message-queue", ]; const command: yargs.CommandModule = { @@ -36,8 +35,8 @@ const command: yargs.CommandModule = { const table = new Table({ head: ["user ID", "Date Added"], colWidths: [40, 40] }); const spinner = ora({ text: "Retrieving workspace users" }).start(); const platform = await twake.run(services); - const userService = platform.getProvider("user"); - const users = await userService.workspaces.getUsers({ workspaceId: argv.id }); + await gr.doInit(platform); + const users = await gr.services.workspaces.getUsers({ workspaceId: argv.id }); spinner.stop(); users diff --git a/twake/backend/node/src/cli/utils/copy-cluster/.gitignore b/twake/backend/node/src/cli/utils/copy-cluster/.gitignore new file mode 100644 index 0000000000..97008e5b86 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-cluster/.gitignore @@ -0,0 +1,2 @@ +node_modules +yarn.lock \ No newline at end of file diff --git a/twake/backend/node/src/cli/utils/copy-cluster/README.md b/twake/backend/node/src/cli/utils/copy-cluster/README.md new file mode 100644 index 0000000000..02fe7cc451 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-cluster/README.md @@ -0,0 +1,4 @@ +Edit the file to your needs + +yarn install +node index.js diff --git a/twake/backend/node/src/cli/utils/copy-cluster/index.js b/twake/backend/node/src/cli/utils/copy-cluster/index.js new file mode 100644 index 0000000000..e478433c55 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-cluster/index.js @@ -0,0 +1,214 @@ +/* eslint-disable */ +var cassandra = require("cassandra-driver"); + +var fromAuthProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var fromContactPoints = [""]; +var fromKeyspace = "twake"; + +var toAuthProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var toContactPoints = [""]; +var toKeyspace = "twake"; + +var forceUpdateAll = false; +var ignoreTables = ["notification"]; +var countersTables = ["statistics", "stats_counter", "channel_counters", "scheduled_queue_counter"]; + +var specialConversions = { + "twake.group_user.date_added": value => { + return new Date(value).getTime(); + }, +}; + +// -- start process + +var fromClient = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: fromContactPoints, + authProvider: fromAuthProvider, + keyspace: fromKeyspace, +}); + +var toClient = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: toContactPoints, + authProvider: toAuthProvider, + keyspace: toKeyspace, + queryOptions: { + consistency: cassandra.types.consistencies.quorum, + }, +}); + +// -- Get all tables and copy schema + +async function client(origin, query, parameters, options) { + return await new Promise((resolve, reject) => { + origin.execute(query, [], {}, function (err, result) { + if (err) { + reject({ err, result }); + } else { + resolve(result); + } + }); + }); +} + +(async () => { + const result = await client( + fromClient, + "SELECT table_name from system_schema.tables WHERE keyspace_name = '" + fromKeyspace + "'", + [], + {}, + ); + for (row of result.rows) { + try { + const fromTable = fromKeyspace + "." + row.table_name; + const toTable = toKeyspace + "." + row.table_name; + + if (ignoreTables.includes(row.table_name)) { + console.log(fromTable.padEnd(50) + " | " + "ignored".padEnd(20) + " | ⏺"); + continue; + } + + let fromCount = 0; + + const destColumns = ( + await client( + toClient, + "SELECT column_name from system_schema.columns where keyspace_name = '" + + toKeyspace + + "' and table_name = '" + + row.table_name + + "'", + [], + {}, + ) + ).rows.map(r => r.column_name); + + try { + const fromResult = await client( + fromClient, + "SELECT count(*) from " + fromTable + "", + [], + {}, + ); + fromCount = parseInt(fromResult.rows[0].count); + } catch (err) { + fromCount = NaN; + } + + if (destColumns.length === 0) { + if (fromCount > 0) + console.log( + fromTable.padEnd(50) + " | " + ("not_in_dest" + "/" + fromCount).padEnd(20) + " | ⏺", + ); + continue; + } + + try { + const toResult = await client(toClient, "SELECT count(*) from " + toTable + "", [], {}); + const toCount = parseInt(toResult.rows[0].count); + + console.log( + fromTable.padEnd(50) + + " | " + + (toCount + "/" + fromCount).padEnd(20) + + " | " + + (toCount >= fromCount ? "✅" : "❌"), + ); + + if (row.table_name.indexOf("counter") >= 0 || countersTables.includes(row.table_name)) { + console.log( + fromTable.padEnd(50) + " | " + ("counter_table" + "/" + fromCount).padEnd(20) + " | 🧮", + ); + if (fromCount > toCount || !fromCount || forceUpdateAll) { + await new Promise(r => { + fromClient.eachRow( + "SELECT JSON * from " + fromTable, + [], + { prepare: true, fetchSize: 1000 }, + async function (n, row) { + // + //TODO handle counters (it is special !) + }, + async function (err, result) { + if (result && result.nextPage) { + await new Promise(r => setTimeout(r, 1000)); + result.nextPage(); + } else { + r(); + } + }, + ); + }); + } + + continue; + } + + if (fromCount > toCount || !fromCount || forceUpdateAll) { + await new Promise(r => { + fromClient.eachRow( + "SELECT JSON * from " + fromTable, + [], + { prepare: true, fetchSize: 1000 }, + async function (n, row) { + try { + const json = JSON.parse(row["[json]"]); + + //The from table can have additional depreciated fields, we need to remove them + const filteredJson = {}; + for (const col of destColumns) { + if ( + typeof json[col] == "string" && + (json[col] || "").match( + /[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]+/, + ) + ) { + json[col] = json[col].split(".")[0]; + } + + if (specialConversions[fromTable + "." + col]) { + json[col] = specialConversions[fromTable + "." + col](json[col]); + } + + if (json[col] !== undefined) filteredJson[col] = json[col]; + } + + await client( + toClient, + "INSERT INTO " + + toTable + + " JSON '" + + JSON.stringify(filteredJson).replace(/'/g, "'$&") + + "'", + [], + {}, + ); + } catch (err) { + console.log(err); + } + }, + async function (err, result) { + if (result && result.nextPage) { + await new Promise(r => setTimeout(r, 1000)); + result.nextPage(); + } else { + r(); + } + }, + ); + }); + } + } catch (err) { + console.log( + fromTable.padEnd(50) + " | " + ("error" + "/" + fromCount).padEnd(20) + " | ❌", + ); + } + } catch (err) { + console.log(err); + continue; + } + + //TODO copy content + } +})(); diff --git a/twake/backend/node/src/cli/utils/copy-cluster/package.json b/twake/backend/node/src/cli/utils/copy-cluster/package.json new file mode 100644 index 0000000000..4a30687891 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-cluster/package.json @@ -0,0 +1,9 @@ +{ + "name": "copy-cluster", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "cassandra-driver": "^4.6.3" + } +} diff --git a/twake/backend/node/src/cli/utils/copy-messages/.gitignore b/twake/backend/node/src/cli/utils/copy-messages/.gitignore new file mode 100644 index 0000000000..97008e5b86 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-messages/.gitignore @@ -0,0 +1,2 @@ +node_modules +yarn.lock \ No newline at end of file diff --git a/twake/backend/node/src/cli/utils/copy-messages/README.md b/twake/backend/node/src/cli/utils/copy-messages/README.md new file mode 100644 index 0000000000..02fe7cc451 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-messages/README.md @@ -0,0 +1,4 @@ +Edit the file to your needs + +yarn install +node index.js diff --git a/twake/backend/node/src/cli/utils/copy-messages/index.js b/twake/backend/node/src/cli/utils/copy-messages/index.js new file mode 100644 index 0000000000..ddaf0d755e --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-messages/index.js @@ -0,0 +1,98 @@ +/* eslint-disable */ +var cassandra = require("cassandra-driver"); + +var fromAuthProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var fromContactPoints = [""]; + +var toAuthProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var toContactPoints = [""]; + +// -- start process + +var fromClient = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: fromContactPoints, + authProvider: fromAuthProvider, + keyspace: "twake", +}); + +var toClient = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: toContactPoints, + authProvider: toAuthProvider, + keyspace: "twake", + queryOptions: { + consistency: cassandra.types.consistencies.quorum, + }, +}); + +// -- Get all tables and copy schema + +async function client(origin, query, parameters, options) { + return await new Promise((resolve, reject) => { + origin.execute(query, [], {}, function (err, result) { + if (err) { + reject({ err, result }); + } else { + resolve(result); + } + }); + }); +} + +// Get all threads and then copy all messages in each threads + +let copiedMessages = 0; +let copiedThreads = 0; + +(async () => { + await new Promise(r => { + fromClient.eachRow( + "SELECT id from twake.threads", + [], + { prepare: true, fetchSize: 50 }, + async function (n, row) { + const threadId = row["id"]; + + console.log("Threads / Messages :", copiedThreads, "/", copiedMessages); + + copiedThreads++; + + await new Promise(r2 => { + fromClient.eachRow( + "SELECT JSON * from twake.messages where thread_id = ? order by id desc", + [threadId], + { prepare: true, fetchSize: 1000 }, + async function (n, row) { + const message = row["[json]"]; + + copiedMessages++; + + await toClient.execute( + "INSERT INTO twake.messages JSON '" + message.replace(/'/g, "'$&") + "'", + [], + { prepare: true }, + ); + }, + async function (err, result) { + if (result && result.nextPage) { + await new Promise(r => setTimeout(r, 100)); + result.nextPage(); + } else { + r2(); + } + }, + ); + }); + }, + async function (err, result) { + if (result && result.nextPage) { + await new Promise(r => setTimeout(r, 2000)); + result.nextPage(); + } else { + r(); + } + }, + ); + }); +})(); diff --git a/twake/backend/node/src/cli/utils/copy-messages/package.json b/twake/backend/node/src/cli/utils/copy-messages/package.json new file mode 100644 index 0000000000..6aa7d4882d --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-messages/package.json @@ -0,0 +1,9 @@ +{ + "name": "copy-messages", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "cassandra-driver": "^4.6.3" + } +} diff --git a/twake/backend/node/src/cli/utils/copy-table/README.md b/twake/backend/node/src/cli/utils/copy-table/README.md new file mode 100644 index 0000000000..02fe7cc451 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-table/README.md @@ -0,0 +1,4 @@ +Edit the file to your needs + +yarn install +node index.js diff --git a/twake/backend/node/src/cli/utils/copy-table/index.js b/twake/backend/node/src/cli/utils/copy-table/index.js new file mode 100644 index 0000000000..112abdae36 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-table/index.js @@ -0,0 +1,88 @@ +/* eslint-disable */ +var cassandra = require("cassandra-driver"); + +var authProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var contactPoints = [""]; +var from = "table_a"; +var to = "table_b"; + +var client = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: contactPoints, + authProvider: authProvider, + keyspace: "twake", +}); + +//Copy object to other table +(async () => { + const query = "SELECT * FROM " + from; + const parameters = []; + + let count = 0; + let max = 0; + let min = new Date().getTime(); + + let rows = []; + + const options = { prepare: true, fetchSize: 1000 }; + + await new Promise(r => { + client.eachRow( + query, + parameters, + options, + function (n, row) { + min = Math.min(parseInt(row.created_at.toString()), min); + max = Math.max(parseInt(row.created_at.toString()), max); + count++; + if (count % 100 == 0) { + console.log(count); + } + rows.push(row); + }, + function (err, result) { + if (result && result.nextPage) { + result.nextPage(); + } else { + r(); + } + }, + ); + }); + + console.log("Downloaded ", count, " rows of ", from, ". Starting copy..."); + + let copyCount = 0; + + for (let i = 0; i < count; i++) { + copyCount++; + if (copyCount % 100 == 0) { + console.log(copyCount, "of", count); + } + + const row = rows[i]; + + await new Promise(r => { + let query = + "UPDATE " + + to + + " SET answers=?, created_at=?, created_by=?, last_activity=?, participants=?, updated_at=? WHERE id=?"; + client.execute( + query, + [ + row.answers, + row.created_at, + row.created_by, + row.last_activity, + row.participants, + row.updated_at, + row.id, + ], + () => { + r(); + }, + ); + }); + } + console.log("Ended with ", count, "threads"); +})(); diff --git a/twake/backend/node/src/cli/utils/copy-table/package.json b/twake/backend/node/src/cli/utils/copy-table/package.json new file mode 100644 index 0000000000..f3c1b49b23 --- /dev/null +++ b/twake/backend/node/src/cli/utils/copy-table/package.json @@ -0,0 +1,6 @@ +{ + "name": "copy-table", + "version": "1.0.0", + "main": "index.js", + "license": "MIT" +} diff --git a/twake/backend/node/src/cli/utils/repair-threads/README.md b/twake/backend/node/src/cli/utils/repair-threads/README.md new file mode 100644 index 0000000000..02fe7cc451 --- /dev/null +++ b/twake/backend/node/src/cli/utils/repair-threads/README.md @@ -0,0 +1,4 @@ +Edit the file to your needs + +yarn install +node index.js diff --git a/twake/backend/node/src/cli/utils/repair-threads/index.js b/twake/backend/node/src/cli/utils/repair-threads/index.js new file mode 100644 index 0000000000..87a00d5ab2 --- /dev/null +++ b/twake/backend/node/src/cli/utils/repair-threads/index.js @@ -0,0 +1,96 @@ +/* eslint-disable */ +var cassandra = require("cassandra-driver"); + +var authProvider = new cassandra.auth.PlainTextAuthProvider("", ""); +var contactPoints = [""]; + +var client = new cassandra.Client({ + localDataCenter: "datacenter1", + contactPoints: contactPoints, + authProvider: authProvider, + keyspace: "twake", +}); + +var threadsTable = "threads"; +var messagesTable = "messages"; + +//Copy object to other table +(async () => { + const query = "SELECT * FROM " + threadsTable + " where answers>1000 allow filtering"; + const parameters = []; + const options = { prepare: true, fetchSize: 1000 }; + + let count = 0; + + let threads = {}; + + await new Promise(r => { + client.eachRow( + query, + parameters, + options, + function (n, row) { + threads[row.id] ||= { answers: 0, id: row.id }; + count++; + }, + function (err, result) { + if (result && result.nextPage) { + result.nextPage(); + } else { + r(); + } + }, + ); + }); + + console.log( + "Downloaded ", + Object.keys(threads).length, + " threads of ", + messagesTable, + ". Starting copy...", + ); + + for (var key of Object.keys(threads)) { + await new Promise(r => { + const query = "SELECT id FROM " + messagesTable + " where thread_id=" + key; + const parameters = []; + const options = { prepare: true, fetchSize: 1000 }; + client.eachRow( + query, + parameters, + options, + function (n, row) { + threads[key].answers++; + }, + function (err, result) { + if (result && result.nextPage) { + result.nextPage(); + } else { + r(); + } + }, + ); + r(); + }); + } + + var copyCount = 0; + for (var key of Object.keys(threads)) { + copyCount++; + if (copyCount % 100 == 0) { + console.log(copyCount, "of", Object.keys(threads)); + } + + const row = threads[key]; + + await new Promise(r => { + let query = "UPDATE " + threadsTable + " SET answers=? WHERE id=?"; + console.log(query, [row.answers, row.id + ""]); + //client.execute(query, [row.answers, row.id], () => { + // r(); + //}); + }); + } + console.log("Ended with ", Object.keys(threads), "threads"); +})(); diff --git a/twake/backend/node/src/cli/utils/repair-threads/package.json b/twake/backend/node/src/cli/utils/repair-threads/package.json new file mode 100644 index 0000000000..dd45de8ae0 --- /dev/null +++ b/twake/backend/node/src/cli/utils/repair-threads/package.json @@ -0,0 +1,9 @@ +{ + "name": "repair-threads", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "cassandra-driver": "^4.6.3" + } +} diff --git a/twake/backend/node/src/core/platform/framework/api/crud-service.ts b/twake/backend/node/src/core/platform/framework/api/crud-service.ts index 329a6057fe..e0ed0e40ca 100644 --- a/twake/backend/node/src/core/platform/framework/api/crud-service.ts +++ b/twake/backend/node/src/core/platform/framework/api/crud-service.ts @@ -125,25 +125,29 @@ export interface ExecutionContext { transport?: "http" | "ws"; } -export class CrudExeption extends Error { +export class CrudException extends Error { constructor(readonly details: string, readonly status: number) { super(); this.message = details; } - static badRequest(details: string): CrudExeption { - return new CrudExeption(details, 400); + static badRequest(details: string): CrudException { + return new CrudException(details, 400); } - static notFound(details: string): CrudExeption { - return new CrudExeption(details, 404); + static notFound(details: string): CrudException { + return new CrudException(details, 404); } - static forbidden(details: string): CrudExeption { - return new CrudExeption(details, 403); + static forbidden(details: string): CrudException { + return new CrudException(details, 403); } - static notImplemented(details: string): CrudExeption { - return new CrudExeption(details, 501); + static notImplemented(details: string): CrudException { + return new CrudException(details, 501); + } + + static badGateway(details: string): CrudException { + return new CrudException(details, 502); } } @@ -158,6 +162,10 @@ export class Pagination implements Paginable { constructor(readonly page_token?: string, readonly limitStr = "100", reversed = false) { this.reversed = reversed; } + + public static fromPaginable(p: Paginable) { + return new Pagination(p.page_token, p.limitStr, p.reversed); + } } export interface CRUDService { diff --git a/twake/backend/node/src/core/platform/framework/api/service.ts b/twake/backend/node/src/core/platform/framework/api/service.ts index bf9a9f4c06..9e9ab64337 100644 --- a/twake/backend/node/src/core/platform/framework/api/service.ts +++ b/twake/backend/node/src/core/platform/framework/api/service.ts @@ -5,7 +5,7 @@ import { TwakeServiceState } from "./service-state"; import { TwakeServiceConfiguration } from "./service-configuration"; import { TwakeContext } from "./context"; import { TwakeServiceOptions } from "./service-options"; -import { PREFIX_METADATA, CONSUMES_METADATA } from "./constants"; +import { CONSUMES_METADATA, PREFIX_METADATA } from "./constants"; import { getLogger, logger } from "../logger"; import { TwakeLogger } from ".."; @@ -22,6 +22,7 @@ export abstract class TwakeService constructor(protected options?: TwakeServiceOptions) { this.state = new BehaviorSubject(TwakeServiceState.Ready); + // REMOVE ME, we should import config from framework folder instead this.configuration = options?.configuration; this.logger = getLogger(`core.platform.services.${this.name}Service`); } diff --git a/twake/backend/node/src/core/platform/framework/api/webservice.ts b/twake/backend/node/src/core/platform/framework/api/webservice.ts new file mode 100644 index 0000000000..394175522f --- /dev/null +++ b/twake/backend/node/src/core/platform/framework/api/webservice.ts @@ -0,0 +1,21 @@ +import { PREFIX_METADATA } from "./constants"; +import { FastifyInstance, FastifyPluginCallback } from "fastify"; + +import gr from "../../../../services/global-resolver"; + +export abstract class AbstractWebService { + abstract routes(fastify: FastifyInstance): void; + + public get prefix(): string { + return Reflect.getMetadata(PREFIX_METADATA, this) || "/"; + } + + public process(): void { + const wrapper: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + this.routes(fastify); + next(); + }; + + gr.fastify.register(wrapper, { prefix: this.prefix }); + } +} diff --git a/twake/backend/node/src/core/platform/framework/decorators/realtime/created.ts b/twake/backend/node/src/core/platform/framework/decorators/realtime/created.ts index 52975bdef1..2f88fb9d3f 100644 --- a/twake/backend/node/src/core/platform/framework/decorators/realtime/created.ts +++ b/twake/backend/node/src/core/platform/framework/decorators/realtime/created.ts @@ -1,6 +1,6 @@ import { CreateResult } from "../../api/crud-service"; import { RealtimeEntityEvent, RealtimeEntityActionType } from "../../../services/realtime/types"; -import { eventBus } from "../../../services/realtime/bus"; +import { websocketEventBus } from "../../../services/realtime/bus"; import { getRealtimeRecipients, getRoom, RealtimeRecipients } from "."; /** @@ -25,7 +25,7 @@ export function RealtimeCreated(recipients: RealtimeRecipients): MethodDec getRealtimeRecipients(recipients, result.entity, context).forEach( ({ room, path, resource }) => { - eventBus.publish(RealtimeEntityActionType.Created, { + websocketEventBus.publish(RealtimeEntityActionType.Created, { type: result.type, room: getRoom(room, result, context), resourcePath: path || "/", diff --git a/twake/backend/node/src/core/platform/framework/decorators/realtime/deleted.ts b/twake/backend/node/src/core/platform/framework/decorators/realtime/deleted.ts index fd7392467c..92b655a9ce 100644 --- a/twake/backend/node/src/core/platform/framework/decorators/realtime/deleted.ts +++ b/twake/backend/node/src/core/platform/framework/decorators/realtime/deleted.ts @@ -1,7 +1,7 @@ import { getRealtimeRecipients, getRoom, RealtimeRecipients } from ".."; import { DeleteResult } from "../../api/crud-service"; import { RealtimeEntityEvent, RealtimeEntityActionType } from "../../../services/realtime/types"; -import { eventBus } from "../../../services/realtime/bus"; +import { websocketEventBus } from "../../../services/realtime/bus"; /** * @@ -25,7 +25,7 @@ export function RealtimeDeleted(recipients: RealtimeRecipients): MethodDec if (result.deleted) getRealtimeRecipients(recipients, result.entity, context).forEach( ({ room, path, resource }) => { - eventBus.publish(RealtimeEntityActionType.Deleted, { + websocketEventBus.publish(RealtimeEntityActionType.Deleted, { type: result.type, room: getRoom(room, result, context), resourcePath: path, diff --git a/twake/backend/node/src/core/platform/framework/decorators/realtime/saved.ts b/twake/backend/node/src/core/platform/framework/decorators/realtime/saved.ts index 6775a55ace..ca19745742 100644 --- a/twake/backend/node/src/core/platform/framework/decorators/realtime/saved.ts +++ b/twake/backend/node/src/core/platform/framework/decorators/realtime/saved.ts @@ -1,7 +1,7 @@ import { getRealtimeRecipients, getRoom, RealtimeRecipients } from ".."; import { SaveResult } from "../../api/crud-service"; import { RealtimeEntityEvent, RealtimeEntityActionType } from "../../../services/realtime/types"; -import { eventBus } from "../../../services/realtime/bus"; +import { websocketEventBus } from "../../../services/realtime/bus"; /** * @@ -25,7 +25,7 @@ export function RealtimeSaved(recipients: RealtimeRecipients): MethodDecor getRealtimeRecipients(recipients, result.entity, context).forEach( ({ room, path, resource }) => { - eventBus.publish(RealtimeEntityActionType.Saved, { + websocketEventBus.publish(RealtimeEntityActionType.Saved, { type: result.type, room: getRoom(room, result, context), resourcePath: path, diff --git a/twake/backend/node/src/core/platform/framework/decorators/realtime/updated.ts b/twake/backend/node/src/core/platform/framework/decorators/realtime/updated.ts index a6b3e0a2f2..53ace2c2b0 100644 --- a/twake/backend/node/src/core/platform/framework/decorators/realtime/updated.ts +++ b/twake/backend/node/src/core/platform/framework/decorators/realtime/updated.ts @@ -1,7 +1,7 @@ import { getRealtimeRecipients, getRoom, RealtimeRecipients } from ".."; import { UpdateResult } from "../../api/crud-service"; import { RealtimeEntityEvent, RealtimeEntityActionType } from "../../../services/realtime/types"; -import { eventBus } from "../../../services/realtime/bus"; +import { websocketEventBus } from "../../../services/realtime/bus"; /** * @@ -24,7 +24,7 @@ export function RealtimeUpdated(recipients: RealtimeRecipients): MethodDec getRealtimeRecipients(recipients, result.entity, context).forEach( ({ room, path, resource }) => { - eventBus.publish(RealtimeEntityActionType.Updated, { + websocketEventBus.publish(RealtimeEntityActionType.Updated, { type: result.type, room: getRoom(room, result, context), resourcePath: path, diff --git a/twake/backend/node/src/core/platform/framework/decorators/webservice.ts b/twake/backend/node/src/core/platform/framework/decorators/webservice.ts new file mode 100644 index 0000000000..0dc1f5c712 --- /dev/null +++ b/twake/backend/node/src/core/platform/framework/decorators/webservice.ts @@ -0,0 +1,8 @@ +import { PREFIX_METADATA } from "../api"; + +export function WebService(prefix: string = "/"): ClassDecorator { + // eslint-disable-next-line @typescript-eslint/ban-types + return function (target: Function): void { + Reflect.defineMetadata(PREFIX_METADATA, prefix, target.prototype); + }; +} diff --git a/twake/backend/node/src/core/platform/framework/event-bus.ts b/twake/backend/node/src/core/platform/framework/event-bus.ts new file mode 100644 index 0000000000..dc6b1ecce8 --- /dev/null +++ b/twake/backend/node/src/core/platform/framework/event-bus.ts @@ -0,0 +1,47 @@ +import { Subject } from "rxjs"; +import { logger as rootLogger } from "./logger"; +import { ExecutionContext } from "./api/crud-service"; + +const logger = rootLogger.child({ + component: "twake.core.platform.framework.event-bus", +}); + +/** + * A local event bus in the platform. Used by platform components and services to communicate using publish subscribe. + */ +class EventBus { + private subjects: Map>; + constructor() { + this.subjects = new Map>(); + } + + subscribe(name: string, listener: (data: T) => void): this { + if (!this.subjects.has(name)) { + this.subjects.set(name, new Subject()); + } + + this.subjects.get(name).subscribe({ + next: (value: T) => { + try { + listener(value); + } catch (err) { + logger.warn({ err }, "Error while calling listener"); + } + }, + }); + + return this; + } + + publish(name: string, data: T, context?: ExecutionContext): boolean { + if (!this.subjects.has(name)) { + return false; + } + + this.subjects.get(name)?.next(data); + + return true; + } +} + +export const localEventBus = new EventBus(); diff --git a/twake/backend/node/src/core/platform/framework/factory.ts b/twake/backend/node/src/core/platform/framework/factory.ts index bf0639a039..315c13f871 100644 --- a/twake/backend/node/src/core/platform/framework/factory.ts +++ b/twake/backend/node/src/core/platform/framework/factory.ts @@ -1,15 +1,15 @@ import { + TwakeContext, TwakeService, + TwakeServiceConfiguration, TwakeServiceOptions, TwakeServiceProvider, - TwakeServiceConfiguration, - TwakeContext, } from "./api"; import { Configuration } from "./configuration"; class StaticTwakeServiceFactory { public async create< - T extends TwakeService = TwakeService + T extends TwakeService = TwakeService, >( module: { new (options?: TwakeServiceOptions): T }, context: TwakeContext, diff --git a/twake/backend/node/src/core/platform/framework/logger.ts b/twake/backend/node/src/core/platform/framework/logger.ts index 2b78e0e95a..8c0aa335d0 100644 --- a/twake/backend/node/src/core/platform/framework/logger.ts +++ b/twake/backend/node/src/core/platform/framework/logger.ts @@ -7,9 +7,9 @@ export type TwakeLogger = pino.Logger; export const logger = pino({ name: "TwakeApp", - level: config.get("level", "info"), + level: config.get("level", "info") || "info", prettyPrint: - process.env.NODE_ENV.indexOf("test") > -1 + process.env.NODE_ENV?.indexOf("test") > -1 ? { translateTime: "HH:MM:ss Z", ignore: "pid,hostname,name", diff --git a/twake/backend/node/src/core/platform/framework/pubsub.ts b/twake/backend/node/src/core/platform/framework/pubsub.ts deleted file mode 100644 index b6b74e4452..0000000000 --- a/twake/backend/node/src/core/platform/framework/pubsub.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Subject } from "rxjs"; -import { logger as rootLogger } from "./logger"; - -const logger = rootLogger.child( - { - component: "twake.core.platform.framework.pubsub" - } -) - -/** - * A local event bus in the platform. Used by platform components and services to communicate using publish subscribe. - */ -class EventBus { - private subjects: Map>; - constructor() { - this.subjects = new Map>(); - } - - subscribe(name: string, listener: (data: T) => void): this { - if (!this.subjects.has(name)) { - this.subjects.set(name, new Subject()); - } - - this.subjects.get(name).subscribe({ - next: (value: T) => { - logger.trace("Got a new value to dispatch to topic '%s': %o", name, value); - try { - listener(value); - } catch (err) { - logger.warn({ err }, "Error while calling listener"); - } - } - }); - - return this; - } - - publish(name: string, data: T): boolean { - if (!this.subjects.has(name)) { - return false; - } - - logger.trace("Publish new value to topic '%s': %o", name, data); - this.subjects.get(name)?.next(data); - - return true; - } -} - -export const localEventBus = new EventBus(); diff --git a/twake/backend/node/src/core/platform/framework/utils/component-utils.ts b/twake/backend/node/src/core/platform/framework/utils/component-utils.ts index 6690be209d..f74697e673 100644 --- a/twake/backend/node/src/core/platform/framework/utils/component-utils.ts +++ b/twake/backend/node/src/core/platform/framework/utils/component-utils.ts @@ -1,22 +1,21 @@ -import { Subject, combineLatest } from "rxjs"; -import { filter } from "rxjs/operators"; +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types */ import { logger, - TwakeServiceFactory, - TwakeContext, TwakeComponent, + TwakeContext, + TwakeServiceFactory, TwakeServiceState, } from "../index"; import { Loader } from "./loader"; export async function buildDependenciesTree( components: Map, - loadComponent: Function, + loadComponent: (name: string) => any, ): Promise { for (const [name, component] of components) { const dependencies: string[] = component.getServiceInstance().getConsumes() || []; - for (let dependencyName of dependencies) { + for (const dependencyName of dependencies) { if (name === dependencyName) { throw new Error(`There is a circular dependency for component ${dependencyName}`); } diff --git a/twake/backend/node/src/core/platform/services/auth/provider.ts b/twake/backend/node/src/core/platform/services/auth/provider.ts index 0b9d743fbd..264430d138 100644 --- a/twake/backend/node/src/core/platform/services/auth/provider.ts +++ b/twake/backend/node/src/core/platform/services/auth/provider.ts @@ -24,7 +24,11 @@ export default interface AuthServiceAPI extends TwakeServiceProvider { generateJWT( userId: uuid, email: string, - options: { track: boolean; provider_id: string; application_id?: string }, + options: { + track: boolean; + provider_id: string; + application_id?: string; + } & any, ): AccessToken; } diff --git a/twake/backend/node/src/core/platform/services/auth/service.ts b/twake/backend/node/src/core/platform/services/auth/service.ts index ab9c94dc53..1fb716fac8 100644 --- a/twake/backend/node/src/core/platform/services/auth/service.ts +++ b/twake/backend/node/src/core/platform/services/auth/service.ts @@ -1,8 +1,9 @@ -import AuthServiceAPI, { JwtConfiguration } from "./provider"; +import { JwtConfiguration } from "./provider"; import jwt from "jsonwebtoken"; import { AccessToken, JWTObject, uuid } from "../../../../utils/types"; import assert from "assert"; import { JwtType } from "../types"; +import AuthServiceAPI from "./provider"; export class AuthService implements AuthServiceAPI { version: "1"; diff --git a/twake/backend/node/src/core/platform/services/counter/provider.ts b/twake/backend/node/src/core/platform/services/counter/provider.ts index 1ee54654a9..3fbb9f7ae9 100644 --- a/twake/backend/node/src/core/platform/services/counter/provider.ts +++ b/twake/backend/node/src/core/platform/services/counter/provider.ts @@ -1,5 +1,6 @@ import Repository from "../database/services/orm/repository/repository"; import { logger } from "../../framework"; +import { ExecutionContext } from "../../framework/api/crud-service"; type LastRevised = { calls: number; @@ -22,13 +23,13 @@ export class CounterProvider { logger.debug(`${this.name} Created counter provider for ${this.repository.table}`); } - async increase(pk: Partial, value: number): Promise { - return this.repository.save(this.repository.createEntityFromObject({ value, ...pk })); + async increase(pk: Partial, value: number, context?: ExecutionContext): Promise { + return this.repository.save(this.repository.createEntityFromObject({ value, ...pk }), context); } - async get(pk: Partial): Promise { + async get(pk: Partial, context?: ExecutionContext): Promise { try { - const counter = await this.repository.findOne(pk); + const counter = await this.repository.findOne(pk, {}, context); const val = counter ? (counter as any).value : 0; return this.revise(pk, val); } catch (e) { @@ -36,12 +37,12 @@ export class CounterProvider { } } - reviseCounter( + setReviseCallback( handler: (pk: Partial) => Promise, maxCalls: number = 10, maxPeriod: number = 24 * 60 * 60 * 1000, ): void { - logger.debug(`${this.name} Set reviseCounter for ${this.repository.table}`); + logger.debug(`${this.name} Set setReviseCallback for ${this.repository.table}`); this.reviseHandler = handler; this.reviseMaxCalls = maxCalls; this.reviseMaxPeriod = maxPeriod; @@ -54,20 +55,27 @@ export class CounterProvider { period: now, }; + logger.debug( + `${this.name} revision status for ${JSON.stringify(pk)} is ${JSON.stringify(lastRevised)}`, + ); + if ( lastRevised.calls >= this.reviseMaxCalls || - now > lastRevised.period + this.reviseMaxPeriod + now > lastRevised.period + this.reviseMaxPeriod || + Math.random() < 1 / Math.max(1, currentValue) //The slowest the number is, the more we update it ) { if (!this.reviseHandler) { - logger.debug(`${this.name} No reviseCounter handler found for ${this.repository.table}`); + logger.debug( + `${this.name} No setReviseCallback handler found for ${this.repository.table}`, + ); return currentValue; } - logger.debug(`${this.name} Execute reviseCounter handler for ${this.repository.table}`); + logger.debug(`${this.name} Execute setReviseCallback handler for ${this.repository.table}`); const actual = await this.reviseHandler(pk); - if (actual != currentValue) { + if (actual !== undefined && actual != currentValue) { await this.increase(pk, actual - currentValue); currentValue = actual; } diff --git a/twake/backend/node/src/core/platform/services/cron/index.ts b/twake/backend/node/src/core/platform/services/cron/index.ts index 36c962b24b..b2e09283da 100644 --- a/twake/backend/node/src/core/platform/services/cron/index.ts +++ b/twake/backend/node/src/core/platform/services/cron/index.ts @@ -25,7 +25,7 @@ export default class CronService extends TwakeService implements CronAP task: cron.schedule(expression, () => { task.lastRun = Date.now(); task.nbRuns++; - this.logger.debug(`Running job ${job.name}`); + this.logger.debug(`Running job ${description || "untitled"}`); try { job(); } catch (err) { diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts index 6cf565eb88..92b41c2711 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/abstract-connector.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types */ import { Connector } from "."; import { ConnectionOptions, DatabaseType } from "../.."; import { FindOptions } from "../repository/repository"; @@ -5,7 +6,8 @@ import { ColumnDefinition, EntityDefinition } from "../types"; import { ListResult } from "../../../../../framework/api/crud-service"; export abstract class AbstractConnector - implements Connector { + implements Connector +{ constructor(protected type: DatabaseType, protected options: T, protected secret: string) {} abstract connect(): Promise; diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts index 210a3aa2ea..319636a70c 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/cassandra.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import cassandra from "cassandra-driver"; +import cassandra, { types } from "cassandra-driver"; import { md5 } from "../../../../../../../crypto"; import { defer, Subject, throwError, timer } from "rxjs"; import { concat, delayWhen, retryWhen, take, tap } from "rxjs/operators"; @@ -27,6 +27,11 @@ export interface CassandraConnectionOptions { password: string; keyspace: string; + /** + * Consistency level + */ + queryOptions: { consistency: number }; + /** * Wait for keyspace and tables to be created at init */ @@ -156,6 +161,7 @@ export class CassandraConnector extends AbstractConnector< const cassandraOptions: cassandra.DseClientOptions = { contactPoints: contactPoints, localDataCenter: this.options.localDataCenter, + queryOptions: {}, }; if (this.options.username && this.options.password) { @@ -165,6 +171,10 @@ export class CassandraConnector extends AbstractConnector< ); } + //Set default consistency level to quorum + cassandraOptions.queryOptions.consistency = + this.options?.queryOptions?.consistency || types.consistencies.quorum; + this.client = new cassandra.Client(cassandraOptions); await this.client.connect(); @@ -456,7 +466,7 @@ export class CassandraConnector extends AbstractConnector< } const query = buildSelectQuery( - (entityType as unknown) as ObjectType
, + entityType as unknown as ObjectType
, filters, options, { diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/typeTransforms.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/typeTransforms.ts index 1b4cbc1eb0..6606e2cebf 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/typeTransforms.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/cassandra/typeTransforms.ts @@ -38,6 +38,9 @@ export const transformValueToDbString = ( options: TransformOptions = {}, ): string => { if (type === "twake_datetime") { + if (isNaN(v) || isNull(v)) { + return "null"; + } return `${v}`; } @@ -45,6 +48,9 @@ export const transformValueToDbString = ( if (isNull(v)) { return "null"; } + if (isNaN(v)) { + return "null"; + } return `${parseInt(v)}`; } if (type === "uuid" || type === "timeuuid") { @@ -141,8 +147,8 @@ export const transformValueFromDbString = ( return decryptedValue; } - if (type === "twake_boolean") { - return Boolean(v); + if (type === "twake_boolean" || type === "boolean") { + return Boolean(v).valueOf(); } if (type === "json") { @@ -154,7 +160,7 @@ export const transformValueFromDbString = ( } if (type === "uuid" || type === "timeuuid") { - return v ? String(v) : null; + return v ? String(v).valueOf() : null; } if (type === "number") { diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts index 433e333456..33d2ce2e22 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/mongodb.ts @@ -188,6 +188,7 @@ export class MongoConnector extends AbstractConnector pk.indexOf(key) < 0) && diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/query-builder.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/query-builder.ts index a74062eea0..91a524795b 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/query-builder.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/query-builder.ts @@ -26,12 +26,14 @@ export function buildSelectQuery( } findOptions.$in = findOptions.$in || []; findOptions.$in.push([key, filters[key]]); - } else { + } else if (columnsDefinition[key]) { where[key] = transformValueToDbString(filters[key], columnsDefinition[key].type, { columns: columnsDefinition[key].options, secret: options.secret, disableSalts: true, }); + } else { + where[key] = filters[key]; } }); diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/typeTransforms.ts b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/typeTransforms.ts index 8cadf3385b..6863c6f3d7 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/typeTransforms.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/connectors/mongodb/typeTransforms.ts @@ -91,8 +91,11 @@ export const transformValueFromDbString = (v: any, type: string, options: any = return null; } } - if (type === "twake_boolean") { - return Boolean(v); + if (type === "twake_boolean" || type === "boolean") { + return Boolean(v).valueOf(); + } + if (type === "number") { + return Number(v).valueOf(); } if (type === "counter") { diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/decorators/column.ts b/twake/backend/node/src/core/platform/services/database/services/orm/decorators/column.ts index a8a977481a..82751bf84b 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/decorators/column.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/decorators/column.ts @@ -7,9 +7,13 @@ export function Column( options: ColumnDefinition["options"] = { order: "ASC" }, ): PropertyDecorator { // eslint-disable-next-line @typescript-eslint/ban-types - return function (target: Object, key: string): void { + return function (target: Object, key: string | symbol) { target.constructor.prototype._columns = target.constructor.prototype._columns || {}; - const colDefinition: ColumnDefinition = { type: type, options: options, nodename: key }; + const colDefinition: ColumnDefinition = { + type: type, + options: options, + nodename: key.toString(), + }; target.constructor.prototype._columns[name] = colDefinition; }; } diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/decorators/entity.ts b/twake/backend/node/src/core/platform/services/database/services/orm/decorators/entity.ts index 82429978c1..088146c1c4 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/decorators/entity.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/decorators/entity.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types */ import { EntityDefinition } from "../types"; type EntityOption = { @@ -15,6 +16,7 @@ type EntityOption = { }; export function Entity(name: string, options: EntityOption): ClassDecorator { + // eslint-disable-next-line @typescript-eslint/ban-types return function (constructor: Function): void { const entityDefinition: EntityDefinition = { name, diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/manager.ts b/twake/backend/node/src/core/platform/services/database/services/orm/manager.ts index d70696f824..42a5a40aae 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/manager.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/manager.ts @@ -6,7 +6,7 @@ import { getEntityDefinition, unwrapPrimarykey } from "./utils"; import { v4 as uuidv4, v1 as uuidv1 } from "uuid"; import { logger } from "../../../../framework"; import { DatabaseEntitiesRemovedEvent, DatabaseEntitiesSavedEvent } from "./types"; -import { localEventBus } from "../../../../framework/pubsub"; +import { localEventBus } from "../../../../framework/event-bus"; export default class EntityManager> { private toPersist: EntityType[] = []; diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/repository/repository.ts b/twake/backend/node/src/core/platform/services/database/services/orm/repository/repository.ts index 67d91aec31..59afe9d1f1 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/repository/repository.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/repository/repository.ts @@ -1,6 +1,10 @@ -import { localEventBus } from "../../../../../../../core/platform/framework/pubsub"; +import { assign } from "lodash"; import { logger } from "../../../../../../../core/platform/framework"; -import { ListResult, Pagination } from "../../../../../framework/api/crud-service"; +import { + ExecutionContext, + ListResult, + Pagination, +} from "../../../../../framework/api/crud-service"; import { Connector } from "../connectors"; import Manager from "../manager"; import { EntityTarget } from "../types"; @@ -17,7 +21,6 @@ type comparisonType = [string, any]; type inType = [string, Array]; // eslint-disable-next-line @typescript-eslint/no-explicit-any type likeType = [string, any]; -import { assign } from "lodash"; export type FindOptions = { pagination?: Pagination; @@ -64,7 +67,11 @@ export default class Repository { return this; } - async find(filters: FindFilter, options: FindOptions = {}): Promise> { + async find( + filters: FindFilter, + options: FindOptions = {}, + context?: ExecutionContext, + ): Promise> { if (!this.entityType) { throw Error(`Unable to find or findOne: EntityType ${this.table} not initialized`); } @@ -76,26 +83,30 @@ export default class Repository { return await this.connector.find(this.entityType, filters, options); } - async findOne(filters: FindFilter, options: FindOptions = {}): Promise { + async findOne( + filters: FindFilter, + options: FindOptions = {}, + context?: ExecutionContext, + ): Promise { if (!options.pagination) { options.pagination = new Pagination("", "1"); } - return (await this.find(filters, options)).getEntities()[0] || null; + return (await this.find(filters, options, context)).getEntities()[0] || null; } - async save(entity: EntityType): Promise { + async save(entity: EntityType, context?: ExecutionContext): Promise { (await this.manager.persist(entity).flush()).reset(); } - async saveAll(entities: EntityType[] = []): Promise { + async saveAll(entities: EntityType[] = [], context?: ExecutionContext): Promise { logger.debug("services.database.repository - Saving entities"); entities.forEach(entity => this.manager.persist(entity)); await (await this.manager.flush()).reset(); } - async remove(entity: EntityType): Promise { + async remove(entity: EntityType, context?: ExecutionContext): Promise { await (await this.manager.remove(entity).flush()).reset(); } diff --git a/twake/backend/node/src/core/platform/services/database/services/orm/utils.ts b/twake/backend/node/src/core/platform/services/database/services/orm/utils.ts index ac6189ac38..a83b096d9f 100644 --- a/twake/backend/node/src/core/platform/services/database/services/orm/utils.ts +++ b/twake/backend/node/src/core/platform/services/database/services/orm/utils.ts @@ -1,13 +1,8 @@ -import crypto, { randomBytes } from "crypto"; -import _ from "lodash"; +import _, { flatten } from "lodash"; import { FindOptions } from "./repository/repository"; import { ColumnDefinition, EntityDefinition, ObjectType } from "./types"; -import { v1 as uuidv1 } from "uuid"; -import { flatten } from "lodash"; -export function getEntityDefinition( - instance: any, -): { +export function getEntityDefinition(instance: any): { entityDefinition: EntityDefinition; columnsDefinition: { [name: string]: ColumnDefinition }; } { @@ -37,6 +32,7 @@ export function unwrapIndexes(entityDefinition: EntityDefinition): string[] { } export function secureOperators( + // eslint-disable-next-line @typescript-eslint/ban-types transformValueToDbString: Function, findOptions: FindOptions = {}, entityType: ObjectType, diff --git a/twake/backend/node/src/core/platform/services/email-pusher/index.ts b/twake/backend/node/src/core/platform/services/email-pusher/index.ts new file mode 100644 index 0000000000..d47a594d13 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/index.ts @@ -0,0 +1,131 @@ +import { getLogger, TwakeLogger, TwakeService } from "../../framework"; +import EmailPusherAPI from "./provider"; +import { + EmailBuilderDataPayload, + EmailBuilderRenderedResult, + EmailBuilderTemplateName, + EmailPusherEmailType, + EmailPusherPayload, + EmailPusherResponseType, +} from "./types"; +import * as Eta from "eta"; +import { convert } from "html-to-text"; +import path from "path"; +import { existsSync } from "fs"; +import axios from "axios"; + +export default class EmailPusherClass + extends TwakeService + implements EmailPusherAPI +{ + readonly name = "email-pusher"; + readonly version: "1.0.0"; + logger: TwakeLogger = getLogger("email-pusher-service"); + apiKey: string; + apiUrl: string; + sender: string; + + api(): EmailPusherAPI { + return this; + } + + async doInit(): Promise { + Eta.configure({ + views: path.join(__dirname, "templates"), + }); + + this.apiUrl = this.configuration.get("endpoint", ""); + this.apiKey = this.configuration.get("api_key", ""); + this.sender = this.configuration.get("sender", ""); + + return this; + } + + /** + * Generate a rendered HTML and text email + * + * @param {EmailBuilderTemplateName} template - the Eta template name + * @param {String} language - the template language + * @param {EmailBuilderDataPayload} data - the data + * @returns {EmailBuilderRenderedResult} - the rendered html and text version + */ + async build( + template: EmailBuilderTemplateName, + language: string, + data: EmailBuilderDataPayload, + ): Promise { + try { + language = ["en", "fr"].find(l => language.toLocaleLowerCase().includes(l)) || "en"; + const templatePath = path.join(__dirname, "templates", language, `${template}.eta`); + const subjectPath = path.join(__dirname, "templates", language, `${template}.subject.eta`); + + if (!existsSync(templatePath)) { + throw Error(`template not found: ${templatePath}`); + } + + if (!existsSync(subjectPath)) { + throw Error(`subject template not found: ${subjectPath}`); + } + + const html = await Eta.renderFile(templatePath, data); + + if (!html || !html.length) { + throw Error("Failed to render template"); + } + + const text = convert(html); + + const subject = convert((await Eta.renderFile(subjectPath, data)) as string); + + return { html, text, subject }; + } catch (error) { + this.logger.error(`Failure when building email template: ${error}`); + } + } + + /** + * Send email + * + * @param {string} to - the recipient + * @param {EmailPusherPayload} email - the email object + * @returns {Promise} + */ + async send( + to: string, + { subject, html: html_body, text: text_body }: EmailPusherPayload, + ): Promise { + try { + if (!html_body || !text_body || !subject || !to) { + throw Error("invalid email"); + } + + const emailObject = { + api_key: this.apiKey, + to: [to], + subject, + text_body, + html_body, + sender: this.sender, + }; + + const { data } = await axios.post( + `${this.apiUrl}`, + emailObject, + ); + + if (data.error && data.error.length) { + throw Error(data.error); + } + + if (data.failed === 1 && data.failures.length) { + throw Error(data.failures.join("")); + } + + if (data.succeeded) { + this.logger.info("email sent"); + } + } catch (error) { + this.logger.error("Failed to send email", error); + } + } +} diff --git a/twake/backend/node/src/core/platform/services/email-pusher/provider.ts b/twake/backend/node/src/core/platform/services/email-pusher/provider.ts new file mode 100644 index 0000000000..fc6c581773 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/provider.ts @@ -0,0 +1,17 @@ +import { TwakeServiceProvider } from "../../framework"; +import { + EmailBuilderDataPayload, + EmailBuilderRenderedResult, + EmailBuilderTemplateName, + EmailPusherPayload, +} from "./types"; + +export default interface EmailPusherAPI extends TwakeServiceProvider { + build( + template: EmailBuilderTemplateName, + language: string, + data: EmailBuilderDataPayload, + ): Promise; + + send(to: string, email: EmailPusherPayload): Promise; +} diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_body.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_body.eta new file mode 100644 index 0000000000..e36e300a50 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_body.eta @@ -0,0 +1,58 @@ + +
+
+ + + + + +
+ +
+ <%~ paragraph %> +
+ +
+ + diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_structure.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_structure.eta new file mode 100644 index 0000000000..e04df4ffec --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_structure.eta @@ -0,0 +1,929 @@ + + + + <%~ it.title %> + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ + + + + + +
+ headerImage +
+
+
+ +
+
+ +
+ + + + + + +
+ <%~ it.body %> +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+
<%~ it.follow_us %>
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ +
+ + + + + + +
+ + + + + + +
+ + instagramIcon + +
+
+
+ +
+ + + + + + +
+ + + + + + +
+ + facebookIcon + +
+
+
+ +
+ + + + + + +
+ + + + + + +
+ + twitterIcon + +
+
+
+ +
+ + + + + + +
+ + + + + + +
+ + youtubeIcon + +
+
+
+ +
+ + + + + + +
+ + + + + + +
+ + githubIcon + +
+
+
+ +
+ +
+
+ +
+ + + + + + +
+ +
+ +
+ + + + + + +
+
Tel + : +33 1 46 96 63 63 • info@linagora.com +
+
+
+ +
+ +
+
+ +
+ + + + + + +
+ +
+ + + + + + +
+
<%~ it.sent_by %> +
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ +
+
+ +
+ + + + + + +
+ +
+
+ +
+ +
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_title.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_title.eta new file mode 100644 index 0000000000..d1797518ed --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/common/_title.eta @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + +
+
You have been invited
+
+
Hi romaric.mollard@gmail + .com, +
+
+
romaric.mollard@gmail.com has invited you to use Twake + on + Crayon Company. +
+
+
Since you already have an account, please sign in and switch your + application as shown here. +
+
\ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/en/_structure.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/_structure.eta new file mode 100644 index 0000000000..0695e6519b --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/_structure.eta @@ -0,0 +1,12 @@ +<%~ includeFile("../common/_structure.eta", Object.assign(it, { + follow_us: "Follow us on social media", + sent_by: "Sent by LINAGORA | 100 Terrasse Boieldieu Tour Franklin 92042 Paris La Défense", + help: "Help center", + privacy: "Privacy Policy", + terms: "Terms of Service", + links: { + help: "https://twake.app/", + privacy: "https://twake.app/en/privacy-policy/", + terms: "https://twake.app/en/terms-of-service/" + } +})) %> \ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.eta new file mode 100644 index 0000000000..db7f25d96d --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.eta @@ -0,0 +1,43 @@ +<% layout('./_structure') %> +<% it.title = 'Missed notifications from company ' + it.company.name %> + +<%~ includeFile("../common/_body.eta", { + paragraphs: [ + ` + + + + + + +
+
+ While you were away +
+
+ `, + ` + + + + + + +
+
+ You have received new messages! 😉 +
+
+ `, + ...it.notifications.map(notification => + includeFile("./notification-digest/notification.eta", notification) + ), + ` + + ` + ] +}) %> \ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.subject.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.subject.eta new file mode 100644 index 0000000000..098a3d20c0 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest.subject.eta @@ -0,0 +1 @@ +Missed notifications in your company <%= it.company.name %> diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest/notification.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest/notification.eta new file mode 100644 index 0000000000..bee473386b --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/en/notification-digest/notification.eta @@ -0,0 +1,20 @@ +
+
+ <%= it.message.user.first_name %> +
+
+
+
+ <%= [it.message.user.first_name, it.message.user.last_name].join(" ") || it.message.user.username %> +
+
+ <%= it.message.text %> +
+
+
+ <%= it.workspace?.name || "Direct chat" %><%= it.workspace?.name ? (" • " + it.channel.name) : "" %> + <%= (new Date(it.message.created_at)).toLocaleDateString("en-US") %> +
+
+
+
\ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/_structure.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/_structure.eta new file mode 100644 index 0000000000..d0fa48b4a4 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/_structure.eta @@ -0,0 +1,12 @@ +<%~ includeFile("../common/_structure.eta", Object.assign(it, { + follow_us: "Retrouvez nous sur les réseaux", + sent_by: "Envoyé par LINAGORA | 100 Terrasse Boieldieu Tour Franklin 92042 Paris La Défense", + help: "Centre d'aide", + privacy: "Confidentialité", + terms: "CGU", + links: { + help: "https://twake.app/", + privacy: "https://twake.app/fr/privacy-policy/", + terms: "https://twake.app/fr/terms-of-service/" + } +})) %> \ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.eta new file mode 100644 index 0000000000..00c4aea734 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.eta @@ -0,0 +1,45 @@ +<% layout('./_structure') %> +<% it.title = 'Notifications manquées de l\'entreprise ' + it.company.name %> + + +<%~ includeFile("../common/_body.eta", { + paragraphs: [ + ` + + + + + + +
+
+ Pendant votre absense +
+
+ `, + ` + + + + + + +
+
+ Vous avez reçu de nouveaux messages! 😉 +
+
+ `, + ...it.notifications.map(notification => + includeFile("./notification-digest/notification.eta", notification) + ) + , + ` + + ` + ] +}) %> \ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.subject.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.subject.eta new file mode 100644 index 0000000000..a402f827e3 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest.subject.eta @@ -0,0 +1 @@ +Notifications manquées dans votre entreprise <%= it.company.name %> diff --git a/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest/notification.eta b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest/notification.eta new file mode 100644 index 0000000000..bee473386b --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/templates/fr/notification-digest/notification.eta @@ -0,0 +1,20 @@ +
+
+ <%= it.message.user.first_name %> +
+
+
+
+ <%= [it.message.user.first_name, it.message.user.last_name].join(" ") || it.message.user.username %> +
+
+ <%= it.message.text %> +
+
+
+ <%= it.workspace?.name || "Direct chat" %><%= it.workspace?.name ? (" • " + it.channel.name) : "" %> + <%= (new Date(it.message.created_at)).toLocaleDateString("en-US") %> +
+
+
+
\ No newline at end of file diff --git a/twake/backend/node/src/core/platform/services/email-pusher/types.ts b/twake/backend/node/src/core/platform/services/email-pusher/types.ts new file mode 100644 index 0000000000..16765ac18d --- /dev/null +++ b/twake/backend/node/src/core/platform/services/email-pusher/types.ts @@ -0,0 +1,50 @@ +import { Channel } from "../../../../services/channels/entities/channel"; +import { Message } from "../../../../services/messages/entities/messages"; +import Company from "../../../../services/user/entities/company"; +import Workspace from "../../../../services/workspaces/entities/workspace"; +import User from "../../../../services/user/entities/user"; +import { UserObject } from "../../../../services/user/web/types"; + +export type EmailBuilderDataPayload = { + user: User; + company: Company; + notifications: { + channel: Channel; + workspace: Workspace; + message: Message & { user: UserObject }; + }[]; +}; + +export type EmailBuilderRenderedResult = { + html: string; + text: string; + subject: string; +}; + +export type EmailBuilderTemplateName = "notification-digest"; + +export type EmailPusherPayload = { + subject: string; + html: string; + text: string; +}; + +export type EmailPusherEmailType = { + sender: string; + html_body: string; + text_body: string; + to: string[]; + subject: string; +}; + +export type EmailPusherResponseType = { + data: { + succeeded: number; + failed: number; + failures: string[]; + error?: string; + error_code?: string; + }; +}; + +export type EmailLanguageType = "en" | "fr"; diff --git a/twake/backend/node/src/core/platform/services/knowledge-graph/api-client.ts b/twake/backend/node/src/core/platform/services/knowledge-graph/api-client.ts new file mode 100644 index 0000000000..5e99b90651 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/knowledge-graph/api-client.ts @@ -0,0 +1,161 @@ +import axios, { AxiosInstance } from "axios"; + +import { + KnowledgeGraphCreateBodyRequest, + KnowledgeGraphCreateCompanyObjectData, + KnowledgeGraphCreateWorkspaceObjectData, + KnowledgeGraphCreateUserObjectData, + KnowledgeGraphCreateChannelObjectData, + KnowledgeGraphCreateMessageObjectData, +} from "./types"; + +import Workspace from "../../../../services/workspaces/entities/workspace"; +import Company from "../../../../services/user/entities/company"; +import User from "../../../../services/user/entities/user"; +import { Channel } from "../../../../services/channels/entities"; +import { Message } from "../../../../services/messages/entities/messages"; +import { getLogger, TwakeLogger } from "../../framework"; + +export default class KnowledgeGraphAPIClient { + protected readonly version = "1.0.0"; + protected readonly axiosInstance: AxiosInstance = axios.create(); + readonly apiUrl: string; + readonly logger: TwakeLogger = getLogger("knowledge-graph-api-client"); + + constructor(apiUrl: string) { + this.apiUrl = apiUrl; + } + + public onCompanyCreated(company: Partial): void { + this.send({ + records: [ + { + key: "null", + value: { + id: "Company", + properties: { + company_id: company.id, + company_name: company.name, + }, + }, + }, + ], + }); + } + + public async onWorkspaceCreated(workspace: Partial): Promise { + const response = await this.send({ + records: [ + { + key: "null", + value: { + id: "Workspace", + properties: { + company_id: workspace.company_id, + workspace_name: workspace.name, + workspace_id: workspace.id, + }, + }, + }, + ], + }); + + if (response.statusText === "OK") { + this.logger.info("onWorkspaceCreated %o", response.config.data); + } + } + + public async onUserCreated(companyId: string, user: Partial): Promise { + const response = await this.send({ + records: [ + { + key: "null", + value: { + id: "User", + properties: { + user_id: user.id, + email: user.email_canonical, + username: user.username_canonical, + user_last_activity: user.last_activity.toLocaleString(), + first_name: user.first_name, + user_created_at: user.creation_date.toLocaleString(), + last_name: user.last_name, + company_id: companyId, + }, + }, + }, + ], + }); + + if (response.statusText === "OK") { + this.logger.info("onUserCreated %o", response.config.data); + } + } + + public async onChannelCreated(channel: Partial): Promise { + const response = await this.send({ + records: [ + { + key: "null", + value: { + id: "Channel", + properties: { + channel_id: channel.id, + channel_name: channel.name, + channel_owner: channel.owner, + workspace_id: channel.workspace_id, + company_id: channel.company_id, + }, + }, + }, + ], + }); + + if (response.statusText === "OK") { + this.logger.info("onChannelCreated %o", response.config.data); + } + } + + public async onMessageCreated( + channelId: string, + message: Partial, + sensitiveData: boolean, + ): Promise { + const response = await this.send({ + records: [ + { + key: "null", + value: { + id: "Message", + properties: { + message_thread_id: message.thread_id, + message_created_at: message.created_at.toLocaleString(), + message_content: sensitiveData ? message.text : "", + type_message: message.type, + message_updated_at: message.updated_at.toLocaleString(), + user_id: message.user_id, + channel_id: channelId, + workspace_id: message.cache?.workspace_id, + company_id: message.cache?.company_id, + }, + }, + }, + ], + }); + + if (response.statusText === "OK") { + this.logger.info("onMessageCreated %o", response.config.data); + } + } + + private async send(data: any) { + return await this.axiosInstance.post< + KnowledgeGraphCreateBodyRequest + >(`${this.apiUrl}/topics/twake`, data, { + headers: { + "Content-Type": "application/vnd.kafka.json.v2+json", + Accept: "application/vnd.kafka.v2+json", + }, + }); + } +} diff --git a/twake/backend/node/src/core/platform/services/knowledge-graph/index.ts b/twake/backend/node/src/core/platform/services/knowledge-graph/index.ts new file mode 100644 index 0000000000..3a10e451d7 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/knowledge-graph/index.ts @@ -0,0 +1,154 @@ +import { Configuration, Consumes, getLogger, TwakeLogger, TwakeService } from "../../framework"; +import { localEventBus } from "../../framework/event-bus"; +import KnowledgeGraphAPI from "./provider"; +import Workspace from "../../../../services/workspaces/entities/workspace"; +import Company from "../../../../services/user/entities/company"; +import User from "../../../../services/user/entities/user"; +import { Channel } from "../../../../services/channels/entities"; +import { Message } from "../../../../services/messages/entities/messages"; +import { KnowledgeGraphGenericEventPayload, KnowledgeGraphEvents } from "./types"; +import KnowledgeGraphAPIClient from "./api-client"; +import gr from "../../../../services/global-resolver"; + +@Consumes([]) +export default class KnowledgeGraphService + extends TwakeService + implements KnowledgeGraphAPI +{ + readonly name = "knowledge-graph"; + readonly version = "1.0.0"; + protected kgAPIClient: KnowledgeGraphAPIClient = this.getKnowledgeGraphApiClient(); + logger: TwakeLogger = getLogger("knowledge-graph-service"); + + async doInit(): Promise { + const use = this.getConfigurationEntry("use"); + + if (!use) { + this.logger.warn("Knowledge graph is not used"); + + return this; + } + + localEventBus.subscribe>( + KnowledgeGraphEvents.COMPANY_CREATED, + this.onCompanyCreated.bind(this), + ); + + localEventBus.subscribe>( + KnowledgeGraphEvents.WORKSPACE_CREATED, + this.onWorkspaceCreated.bind(this), + ); + + localEventBus.subscribe>( + KnowledgeGraphEvents.CHANNEL_CREATED, + this.onChannelCreated.bind(this), + ); + + localEventBus.subscribe>( + KnowledgeGraphEvents.MESSAGE_CREATED, + this.onMessageCreated.bind(this), + ); + + localEventBus.subscribe>( + KnowledgeGraphEvents.USER_CREATED, + this.onUserCreated.bind(this), + ); + + return this; + } + + async onCompanyCreated(data: KnowledgeGraphGenericEventPayload): Promise { + this.logger.info(`${KnowledgeGraphEvents.COMPANY_CREATED} %o`, data); + + if (this.kgAPIClient && (await this.shouldForwardEvent([data.resource.id]))) { + this.kgAPIClient.onCompanyCreated(data.resource); + } + } + + async onWorkspaceCreated(data: KnowledgeGraphGenericEventPayload): Promise { + this.logger.info(`${KnowledgeGraphEvents.WORKSPACE_CREATED} %o`, data); + + if (this.kgAPIClient && (await this.shouldForwardEvent([data.resource.company_id]))) { + this.kgAPIClient.onWorkspaceCreated(data.resource); + } + } + + async onChannelCreated(data: KnowledgeGraphGenericEventPayload): Promise { + this.logger.info(`${KnowledgeGraphEvents.CHANNEL_CREATED} %o`, data); + + if (this.kgAPIClient && (await this.shouldForwardEvent([data.resource.company_id]))) { + this.kgAPIClient.onChannelCreated(data.resource); + } + } + + async onMessageCreated(data: KnowledgeGraphGenericEventPayload): Promise { + this.logger.debug(`${KnowledgeGraphEvents.MESSAGE_CREATED} %o`, data); + + const allowedToShare = await this.shouldForwardEvent( + [data.resource.cache.company_id], + data.resource.user_id, + ); + + if (this.kgAPIClient && allowedToShare) { + this.kgAPIClient.onMessageCreated( + data.resource.cache.company_id, + data.resource, + allowedToShare === "all", + ); + } + } + + async onUserCreated(data: KnowledgeGraphGenericEventPayload): Promise { + this.logger.info(`${KnowledgeGraphEvents.USER_CREATED} %o`, data); + + if ( + this.kgAPIClient && + (await this.shouldForwardEvent(data.resource.cache?.companies || [], data.resource.id)) + ) { + for (const companyId of data.resource.cache?.companies || []) { + this.kgAPIClient.onUserCreated(companyId, data.resource); + } + } + } + + private getConfigurationEntry(key: string): T { + const configuration = new Configuration("knowledge-graph"); + return configuration.get(key); + } + + private getKnowledgeGraphApiClient(): KnowledgeGraphAPIClient { + const endpoint = this.getConfigurationEntry("endpoint"); + + if (endpoint && endpoint.length) { + this.kgAPIClient = new KnowledgeGraphAPIClient(endpoint); + } else { + this.logger.info("KnowledgeGraph - No endpoint defined in default.json"); + } + + return this.kgAPIClient; + } + + async shouldForwardEvent( + companyIds: string[] | null, + userId?: string, + ): Promise { + const user = userId ? await gr.services.users.get({ id: userId }) : null; + const forwardedCompanies = this.getConfigurationEntry("forwarded_companies"); + const isCompanyForwarded = !!(companyIds || []).find(v => forwardedCompanies.includes(v)); + if (user?.preferences && !user.preferences.knowledge_graph) + user.preferences.knowledge_graph = "metadata"; + return (!userId || (user && user.preferences?.knowledge_graph !== "nothing")) && + (!companyIds || + companyIds.length === 0 || + isCompanyForwarded || + forwardedCompanies.length === 0) + ? user + ? (user.preferences.knowledge_graph as "all" | "metadata") + : "all" + : false; + } + + api(): KnowledgeGraphAPI { + return this; + } +} diff --git a/twake/backend/node/src/core/platform/services/knowledge-graph/provider.ts b/twake/backend/node/src/core/platform/services/knowledge-graph/provider.ts new file mode 100644 index 0000000000..435492f8e9 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/knowledge-graph/provider.ts @@ -0,0 +1,15 @@ +import Company from "../../../../services/user/entities/company"; +import { Channel } from "../../../../services/channels/entities"; +import { TwakeServiceProvider } from "../../framework"; +import { KnowledgeGraphGenericEventPayload } from "./types"; +import Workspace from "../../../../services/workspaces/entities/workspace"; +import { Message } from "../../../../services/messages/entities/messages"; +import User from "../../../../services/user/entities/user"; + +export default interface KnowledgeGraphAPI extends TwakeServiceProvider { + onCompanyCreated(data: KnowledgeGraphGenericEventPayload): void; + onWorkspaceCreated(data: KnowledgeGraphGenericEventPayload): void; + onChannelCreated(data: KnowledgeGraphGenericEventPayload): void; + onMessageCreated(data: KnowledgeGraphGenericEventPayload): void; + onUserCreated(data: KnowledgeGraphGenericEventPayload): void; +} diff --git a/twake/backend/node/src/core/platform/services/knowledge-graph/types.ts b/twake/backend/node/src/core/platform/services/knowledge-graph/types.ts new file mode 100644 index 0000000000..aebc1249df --- /dev/null +++ b/twake/backend/node/src/core/platform/services/knowledge-graph/types.ts @@ -0,0 +1,92 @@ +export type KnowledgeGraphCreateCompanyObjectData = { + key: string; + value: { + id: string; + properties: { + company_id: string; + company_name: string; + }; + }; +}; + +export type KnowledgeGraphCreateWorkspaceObjectData = { + key: string; + value: { + id: string; + properties: { + company_id: string; + workspace_name: string; + workspace_id: string; + }; + }; +}; + +export type KnowledgeGraphCreateUserObjectData = { + key: string; + value: { + id: string; + properties: { + user_id: string; + email: string; + username: string; + user_last_activity: string; + first_name: string; + user_created_at: string; + last_name: string; + company_id: string; + }; + }; +}; + +export type KnowledgeGraphCreateChannelObjectData = { + key: string; + value: { + id: string; + properties: { + channel_id: string; + channel_name: string; + channel_owner: string; + workspace_id: string; + }; + }; +}; + +export type KnowledgeGraphCreateMessageObjectData = { + key: string; + value: { + id: string; + properties: { + message_thread_id: string; + message_created_at: string; + message_content: string; + type_message: string; + message_updated_at: string; + user_id: string; + channel_id: string; + }; + }; +}; + +export type KnowledgeGraphCreateBodyRequest = { + records: T; +}; + +export type KnowledgeGraphRelationLinkObject = { + relation: "mention" | "sender" | "parent" | "children" | "owner"; + type: "user" | "channel" | "workspace" | "company" | "message"; + id: string; +}; + +export type KnowledgeGraphGenericEventPayload = { + id: string; + resource: Partial; + links: KnowledgeGraphRelationLinkObject[]; +}; + +export enum KnowledgeGraphEvents { + COMPANY_CREATED = "kg:company:created", + WORKSPACE_CREATED = "kg:workspace:created", + CHANNEL_CREATED = "kg:channel:created", + MESSAGE_CREATED = "kg:message:created", + USER_CREATED = "kg:user:created", +} diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/client.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/client.ts similarity index 98% rename from twake/backend/node/src/core/platform/services/pubsub/amqp/client.ts rename to twake/backend/node/src/core/platform/services/message-queue/amqp/client.ts index 630c0e09b6..a6e5dc8d7a 100644 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/client.ts +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/client.ts @@ -2,7 +2,7 @@ import { logger } from "../../../framework/logger"; import { constants as CONSTANTS } from "./constants"; import { ConfirmChannel, Replies, Message, Options, ConsumeMessage } from "amqplib"; -const LOG_PREFIX = "service.pubsub.amqp.AmqpClient -"; +const LOG_PREFIX = "service.message-queue.amqp.AmqpClient -"; export type AmqpCallbackType = ( err: Error, diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/constants.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/constants.ts similarity index 85% rename from twake/backend/node/src/core/platform/services/pubsub/amqp/constants.ts rename to twake/backend/node/src/core/platform/services/message-queue/amqp/constants.ts index 7aba7bba3c..8601b35963 100644 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/constants.ts +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/constants.ts @@ -17,7 +17,7 @@ export const constants = { }, SUBSCRIBER: { - queueName: "", // This is the pubsub pattern with amqp, the server allocates a free queue name for us + queueName: "", // This is the message-queue pattern with amqp, the server allocates a free queue name for us queueOptions: { exclusive: true, durable: false, diff --git a/twake/backend/node/src/core/platform/services/message-queue/amqp/index.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/index.ts new file mode 100644 index 0000000000..4c14a20d61 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/index.ts @@ -0,0 +1,76 @@ +import { Subscription } from "rxjs"; +import { logger as rootLogger } from "../../../framework/logger"; +import { + MessageQueueAdapter, + MessageQueueClient, + MessageQueueListener, + MessageQueueMessage, + MessageQueueSubscriptionOptions, +} from "../api"; +import MessageQueueProxy from "../proxy"; +import { AMQPMessageQueueManager } from "./manager"; +import { SkipCLI } from "../../../framework/decorators/skip"; + +const logger = rootLogger.child({ + component: "twake.core.platform.services.message-queue.amqp", +}); + +export class AMQPMessageQueueService implements MessageQueueAdapter { + version: "1"; + clientProxy: MessageQueueProxy; + availableSubscription: Subscription; + unavailableSubscription: Subscription; + manager: AMQPMessageQueueManager; + type: "amqp"; + + constructor(private urls: string[]) { + this.manager = new AMQPMessageQueueManager(); + this.clientProxy = new MessageQueueProxy(); + } + + @SkipCLI() + async init(): Promise { + logger.info("Initializing message-queue service implementation with urls %o", this.urls); + await this.manager.createClient(this.urls); + + this.availableSubscription = this.manager.getClientAvailable().subscribe({ + next: (client: MessageQueueClient) => { + logger.info("A new message-queue client is available"); + this.clientProxy.setClient(client); + }, + error: () => { + logger.error("Error while listening to message-queue client availability"); + }, + }); + + this.unavailableSubscription = this.manager.getClientUnavailable().subscribe({ + next: (err: Error) => { + logger.warn({ err }, "Client is not available anymore"); + this.clientProxy.unsetClient(); + }, + error: () => { + logger.error("Error while listening to message-queue client unavailability"); + }, + }); + + return this; + } + + async stop(): Promise { + logger.info("Closing message-queue service"); + await this.clientProxy.close(); + return this; + } + + publish(topic: string, message: MessageQueueMessage): Promise { + return this.clientProxy.publish(topic, message); + } + + subscribe( + topic: string, + listener: MessageQueueListener, + options?: MessageQueueSubscriptionOptions, + ): Promise { + return this.clientProxy.subscribe(topic, listener, options); + } +} diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/manager.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/manager.ts similarity index 78% rename from twake/backend/node/src/core/platform/services/pubsub/amqp/manager.ts rename to twake/backend/node/src/core/platform/services/message-queue/amqp/manager.ts index fd9b142dff..276671a887 100644 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/manager.ts +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/manager.ts @@ -2,19 +2,19 @@ import { ConfirmChannel } from "amqplib"; import { AmqpConnectionManager, connect } from "amqp-connection-manager"; import { ReplaySubject, Subject } from "rxjs"; import { logger } from "../../../framework/logger"; -import { AmqpPubsubClient } from "./pubsubclient"; -import { PubsubClientManager, PubsubClient } from "../api"; +import { AmqpMessageQueueClient } from "./pubsubclient"; +import { MessageQueueClientManager, MessageQueueClient } from "../api"; import { AMQPPubSub } from "./pubsub"; -const LOG_PREFIX = "service.pubsub.amqp.AMQPPubsubManager -"; +const LOG_PREFIX = "service.pubsub.amqp.AMQPMessageQueueManager -"; -export class AMQPPubsubManager implements PubsubClientManager { +export class AMQPMessageQueueManager implements MessageQueueClientManager { // using ReplaySubjects will allow to get the data which has been published before the subscriptions - private clientAvailable: Subject = new ReplaySubject(1); + private clientAvailable: Subject = new ReplaySubject(1); private clientUnavailable: Subject = new ReplaySubject(1); private connected = false; - getClientAvailable(): Subject { + getClientAvailable(): Subject { return this.clientAvailable; } @@ -22,7 +22,7 @@ export class AMQPPubsubManager implements PubsubClientManager { return this.clientUnavailable; } - async createClient(urls: string[]): Promise> { + async createClient(urls: string[]): Promise> { logger.info(`${LOG_PREFIX} Creating AMQP client %o`, urls); const connection = connect(urls); @@ -54,7 +54,7 @@ export class AMQPPubsubManager implements PubsubClientManager { return this.clientAvailable; } - private create(connection: AmqpConnectionManager): Promise { + private create(connection: AmqpConnectionManager): Promise { logger.info(`${LOG_PREFIX} Creating AMQP Channel`); const channel = connection.createChannel({ name: "Twake" }); @@ -70,10 +70,10 @@ export class AMQPPubsubManager implements PubsubClientManager { logger.info(`${LOG_PREFIX} Channel creation error`); }); - return new Promise(resolve => { + return new Promise(resolve => { channel.addSetup((channel: ConfirmChannel) => { logger.info(`${LOG_PREFIX} Channel setup is complete`); - const client = new AmqpPubsubClient(channel); + const client = new AmqpMessageQueueClient(channel); // First attempt if (!this.connected) { diff --git a/twake/backend/node/src/core/platform/services/message-queue/amqp/pubsub.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/pubsub.ts new file mode 100644 index 0000000000..1c0dbd4e8c --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/pubsub.ts @@ -0,0 +1,70 @@ +import { logger } from "../../../framework/logger"; +import { AmqpMessageQueueClient } from "./pubsubclient"; +import { + MessageQueueMessage, + MessageQueueListener, + MessageQueueClient, + MessageQueueSubscriptionOptions, +} from "../api"; +import { AmqpCallbackType, SubscribeOptions } from "./client"; + +const LOG_PREFIX = "service.message-queue.amqp.AMQPPubSub -"; + +/** + * Implementation of MessageQueueClient based on AMQP + */ +export class AMQPPubSub implements MessageQueueClient { + constructor(private client: AmqpMessageQueueClient) {} + + close(): Promise { + return this.client.dispose(); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + async publish(topic: string, message: MessageQueueMessage): Promise { + logger.debug(`${LOG_PREFIX} Publishing message to topic ${topic}`); + await this.client.publish(topic, message.data, { ttl: message.ttl }); + } + + subscribe( + topic: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + listener: MessageQueueListener, + options: MessageQueueSubscriptionOptions = { unique: false, queue: null, ttl: -1 }, + ): Promise { + const subscribeOptions: SubscribeOptions = {}; + logger.debug(`${LOG_PREFIX} Subscribing to topic ${topic} with options %o`, options); + + const callback: AmqpCallbackType = (err, message, originalMessage) => { + const data = err ? originalMessage : message; + + if (err) { + logger.error( + `${LOG_PREFIX} Received a message which can not be parsed on topic ${topic}: %o`, + originalMessage?.content.toString(), + ); + } + + listener({ + data, + ack: (): void => { + logger.debug(`${LOG_PREFIX} Ack message on topic ${topic}`); + this.client.ack(originalMessage); + }, + }); + }; + + if (options.ttl && options.ttl > 0) { + subscribeOptions.ttl = options.ttl; + } + + return options?.unique + ? this.client.subscribeToDurableQueue( + topic, + options?.queue || topic, + subscribeOptions, + callback, + ) + : this.client.subscribe(topic, subscribeOptions, callback); + } +} diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/pubsubclient.ts b/twake/backend/node/src/core/platform/services/message-queue/amqp/pubsubclient.ts similarity index 95% rename from twake/backend/node/src/core/platform/services/pubsub/amqp/pubsubclient.ts rename to twake/backend/node/src/core/platform/services/message-queue/amqp/pubsubclient.ts index b4f4d3a567..996bbef4c2 100644 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/pubsubclient.ts +++ b/twake/backend/node/src/core/platform/services/message-queue/amqp/pubsubclient.ts @@ -4,12 +4,12 @@ import { AmqpClient, AmqpCallbackType, PublishOptions, SubscribeOptions } from " import { Options } from "amqplib"; import _ from "lodash"; -const LOG_PREFIX = "service.pubsub.amqp.AmqpPubsubClient -"; +const LOG_PREFIX = "service.message-queue.amqp.AmqpMessageQueueClient -"; /** - * AMQP client abstracting low level channel methods to create a pubsub-like implementation + * AMQP client abstracting low level channel methods to create a message-queue-like implementation */ -export class AmqpPubsubClient extends AmqpClient { +export class AmqpMessageQueueClient extends AmqpClient { publish(topic: string, data: unknown, options?: PublishOptions): Promise { data = _.cloneDeep(data); diff --git a/twake/backend/node/src/core/platform/services/message-queue/api.ts b/twake/backend/node/src/core/platform/services/message-queue/api.ts new file mode 100644 index 0000000000..3df4475cfa --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/api.ts @@ -0,0 +1,338 @@ +import { Subject } from "rxjs"; +import { v4 as uuidv4 } from "uuid"; +import { Initializable, logger, TwakeServiceProvider } from "../../framework"; +import { Processor } from "./processor"; +import { ExecutionContext } from "../../framework/api/crud-service"; + +export type MessageQueueType = "local" | "amqp"; + +export interface MessageQueueMessage { + /** + * Optional message id, mainly used for logs + */ + id?: string; + + /** + * The message TTL period in milliseconds + */ + ttl?: number; + + /** + * The message payload to process + */ + data: T; +} + +export interface MessageQueueEventMessage extends MessageQueueMessage { + topic: string; +} + +export interface IncomingMessageQueueMessage extends MessageQueueMessage { + ack: () => void; +} + +export type MessageQueueSubscriptionOptions = { + /** + * A unique subscription guaranties that there will be only one listener consuming the message on the subscription topic even if many are subscribing to the same topic from several places (not only from the current instance/host). + * Also, it will guaranties that messages which were published before any subscriber subscribes will be consumed. + */ + unique?: boolean; + + /** + * Automatically acknowledge the incoming message when the processing is complete + */ + ack?: boolean; + + /** + * Use custom named queue instead of using same name as exchange. Can be useful when we have multiple subsciptions on the same topic. + */ + queue?: string | null; + + /** + * Configures the message TTL (in ms) in the underlying messaging system. + * Negative or undefined means no TTL. + * Notes: + * - If supported by the messaging system, messages will not be delivered to the application. + * - If not supported, this may be up to the subscriber itself to filter messages at the application level based on some timestamp if available. + */ + ttl?: number | null; +}; + +export type MessageQueueListener = (message: IncomingMessageQueueMessage) => void; + +export interface MessageQueueServiceAPI extends TwakeServiceProvider { + /** + * Publish a message to a given topic + * @param topic The topic to publish the message to + * @param message The message to publish to the topic + * @param context + */ + publish( + topic: string, + message: MessageQueueMessage, + context?: ExecutionContext, + ): Promise; + + /** + * Subscribe the a topic. The listener will be called when a new message is published in the topic (this may not be true based on the options parameters). + * @param topic The topic to subsribe to + * @param listener The function which will process the message published in the topic + * @param options The subscription options. If not defined, the subscriber will be called for all messages available in the topic. + */ + subscribe( + topic: string, + listener: MessageQueueListener, + options?: MessageQueueSubscriptionOptions, + ): Promise; + + /** + * The messages processor instance + */ + processor: Processor; + + stop(): Promise; + start(): Promise; +} + +export type MessageQueueAdapter = Pick & { + type: string; + init?(): Promise; + start?(): Promise; + stop?(): Promise; +}; + +export type MessageQueueClient = Pick & { + /** + * Close the client + */ + close?(): Promise; +}; + +/** + * The client manager allows to get notified when a client is available and then becomes unavailable. + */ +export interface MessageQueueClientManager { + /** + * Ask for a new client to be created + */ + createClient(config: string[]): Promise>; + + /** + * Subject when a client is available + */ + getClientAvailable(): Subject; + + /** + * Subject when a client becomes unavailable + */ + getClientUnavailable(): Subject; +} + +/** + * Manages the message-queue client adding mechanisms to cache subscriptions and messages to publish. + */ +export interface MessageQueueProxy extends MessageQueueClient { + /** + * Set a new client to use replacing any existing one. + * The new client will reuse all the subscriptions automatically. + * @param client + */ + setClient(client: MessageQueueClient): Promise; + + /** + * Remove the client. This will close any underlying connection but will not remove any subscription. + */ + unsetClient(): Promise; +} + +export interface MessageQueueEventBus { + /** + * Subscribes to events + */ + subscribe(listener: (message: MessageQueueEventMessage) => void): this; + + /** + * Publish message in event bus + */ + publish(message: MessageQueueEventMessage): boolean; +} + +export abstract class MessageQueueServiceSubscription { + protected messageQueue: MessageQueueServiceAPI; + + async subscribe(messageQueue: MessageQueueServiceAPI): Promise { + if (!messageQueue) { + throw new Error("message-queue service it not defined"); + } + this.messageQueue = messageQueue; + + return this.doSubscribe(); + } + + abstract doSubscribe(): Promise; +} + +export class MessageQueueServiceProcessor + extends MessageQueueServiceSubscription + implements Initializable +{ + constructor( + protected handler: MessageQueueHandler, + protected messageQueue: MessageQueueServiceAPI, + ) { + super(); + } + + async init(): Promise { + try { + await this.subscribe(this.messageQueue); + } catch (err) { + logger.warn( + { err }, + `MessageQueueServiceProcessor.handler.${this.handler.name} - Not able to start handler`, + ); + } + + return this; + } + + async stop(): Promise { + // TODO + return this; + } + + async process(message: IncomingMessageQueueMessage): Promise { + logger.info( + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Processing message`, + ); + return this.handler.process(message.data); + } + + async doSubscribe(): Promise { + //TODO this is where we do not receive the call + + if (this.handler.topics && this.handler.topics.in) { + logger.info( + `MessageQueueServiceProcessor.handler.${this.handler.name} - Subscribing to topic ${this.handler?.topics?.in} with options %o`, + this.handler.options, + ); + await this.messageQueue.subscribe( + this.handler.topics.in, + this.processMessage.bind(this), + this.handler.options, + ); + } + } + + private async processMessage(message: IncomingMessageQueueMessage): Promise { + if (!message.id) { + message.id = uuidv4(); + } + + if (this.handler.validate) { + const isValid = this.handler.validate(message.data); + + if (!isValid) { + logger.error( + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Message is invalid`, + ); + + //Validate rabbitmq message, we will not process it again + if (this.handler?.options?.ack && message?.ack) message?.ack(); + return; + } + } + + try { + const result = await this.process(message); + if (this.handler?.options?.ack && message?.ack) { + logger.debug( + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Acknowledging message %o`, + message, + ); + message?.ack(); + } + + if (result) { + await this.sendResult(message, result); + } + } catch (error) { + this.handleError(message, error); + + //Fixme Validate message because we don't have max retry handler + if (this.handler?.options?.ack && message?.ack) message?.ack(); + } + } + + private async sendResult(message: IncomingMessageQueueMessage, result: Out): Promise { + if (!this.handler.topics.out) { + logger.info( + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Message processing result is skipped`, + ); + return; + } + + logger.info( + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Sending processing result to ${this.handler.topics.out}`, + ); + + return this.messageQueue.publish(this.handler.topics.out, { + id: uuidv4(), + data: result, + }); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private async handleError(message: IncomingMessageQueueMessage, err: any) { + logger.error( + { err }, + `MessageQueueServiceProcessor.handler.${this.handler.name}:${message.id} - Error while processing message`, + ); + if (this.handler.topics.error) { + this.messageQueue.publish(this.handler.topics.error, { + data: { + type: "error", + id: message.id, + message: err instanceof Error ? (err as Error).message : String(err), + }, + }); + } + } +} + +/** + * A message-queue handler is in charge of processing message from a topic and publishing the processing result to another topic + */ +export interface MessageQueueHandler extends Initializable { + readonly topics: { + // The topic to subscribe to + in: string; + // The topic to push process result to if defined + out?: string; + // The topic to push error to. When topic is undefined, do not push the error + error?: string; + }; + + /** + * Options subscriber options + */ + readonly options?: MessageQueueSubscriptionOptions; + + /** + * The handler name + */ + readonly name: string; + + /** + * Validate the input message + * + * @param message message to validate + */ + validate?(message: InputMessage): boolean; + + /** + * Process the message and potentially produces result which will be published elsewhere + * @param message + */ + process(message: InputMessage): Promise; +} diff --git a/twake/backend/node/src/core/platform/services/message-queue/bus.ts b/twake/backend/node/src/core/platform/services/message-queue/bus.ts new file mode 100644 index 0000000000..9d0ecff42f --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/bus.ts @@ -0,0 +1,36 @@ +import { EventEmitter } from "events"; +import { MessageQueueEventBus, MessageQueueEventMessage } from "./api"; +const EVENT = Symbol("event"); + +/** + * Event bus is used by the MessageQueue decorators to publish data to be send to message-queue service. + * The message-queue service is the only subscriber of the event bus. + * By decoupling decorator and service, events will not be published when the service is not enabled. + */ +class EventBus extends EventEmitter implements MessageQueueEventBus { + constructor() { + super(); + } + + /** + * Subscribe is MUST only be used by the message-queue service + * + * @param listener + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + subscribe(listener: (message: MessageQueueEventMessage) => void): this { + return this.on(EVENT, listener); + } + + /** + * Publish must only be used by the MessageQueue decorators + * + * @param message + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + publish(message: MessageQueueEventMessage): boolean { + return this.emit(EVENT, message); + } +} + +export const eventBus = new EventBus(); diff --git a/twake/backend/node/src/core/platform/services/message-queue/factory.ts b/twake/backend/node/src/core/platform/services/message-queue/factory.ts new file mode 100644 index 0000000000..fbf39f9a11 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/factory.ts @@ -0,0 +1,38 @@ +import { MessageQueueAdapter, MessageQueueType } from "./api"; +import { AMQPMessageQueueService } from "./amqp"; +import { LocalMessageQueueService } from "./local"; +import { TwakeServiceConfiguration, logger as rootLogger } from "../../framework"; + +const logger = rootLogger.child({ + component: "twake.core.platform.services.message-queue.factory", +}); + +const DEFAULT_AMQP_URL = "amqp://guest:guest@localhost:5672"; +const DEFAULT_ADAPTER = "amqp"; + +export class MessageQueueAdapterFactory { + public create(configuration: TwakeServiceConfiguration): MessageQueueAdapter { + const type: MessageQueueType = configuration.get("type", DEFAULT_ADAPTER); + + logger.info("Building Adapter %o", type); + + switch (type) { + case "local": + return new LocalMessageQueueService(); + case "amqp": + let urls: string[] = configuration.get("amqp.urls", [DEFAULT_AMQP_URL]); + + //For environment variables + if (typeof urls === "string") { + urls = (urls as string).split(","); + } + + return new AMQPMessageQueueService(urls); + default: + logger.error("Adapter '%o' is not supported", type); + throw new Error(`${type} is not supported`); + } + } +} + +export default new MessageQueueAdapterFactory(); diff --git a/twake/backend/node/src/core/platform/services/message-queue/index.ts b/twake/backend/node/src/core/platform/services/message-queue/index.ts new file mode 100644 index 0000000000..cb5393e31b --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/index.ts @@ -0,0 +1,101 @@ +import { TwakeService, ServiceName, logger as rootLogger } from "../../framework"; +import { + MessageQueueAdapter, + MessageQueueListener, + MessageQueueMessage, + MessageQueueServiceAPI, + MessageQueueSubscriptionOptions, +} from "./api"; +import { eventBus } from "./bus"; +import { Processor } from "./processor"; +import adapterFactory from "./factory"; +import { SkipCLI } from "../../framework/decorators/skip"; +import config from "../../../../core/config"; + +const logger = rootLogger.child({ + component: "twake.core.platform.services.message-queue", +}); +@ServiceName("message-queue") +export default class MessageQueue extends TwakeService { + version = "1"; + name = "message-queue"; + service: MessageQueueService; + + async doInit(): Promise { + this.service = new MessageQueueService( + //Old config name was "pubsub" + adapterFactory.create(this.configuration || config.get("pubsub")), + ); + await this.service.init(); + + eventBus.subscribe(message => { + logger.info(`Event bus publishing message to ${message.topic}`); + this.service.publish(message.topic, { data: message.data }); + }); + + return this; + } + + async doStart(): Promise { + await this.service.start(); + + return this; + } + + async doStop(): Promise { + await this.service.stop(); + + return this; + } + + api(): MessageQueueServiceAPI { + return this.service; + } +} + +export class MessageQueueService implements MessageQueueServiceAPI { + version: "1"; + processor: Processor; + + constructor(private adapter: MessageQueueAdapter) { + this.processor = new Processor(this); + } + + @SkipCLI() + async init(): Promise { + logger.info("Initializing message-queue adapter %o", this.adapter.type); + await this.adapter?.init?.(); + + return this; + } + + @SkipCLI() + async start(): Promise { + logger.info("Starting message-queue adapter %o", this.adapter.type); + await this.adapter?.start?.(); + await this.processor.start(); + + return this; + } + + @SkipCLI() + async stop(): Promise { + logger.info("Stopping message-queue adapter %o", this.adapter.type); + await this.adapter?.stop?.(); + await this.processor.stop(); + + return this; + } + + publish(topic: string, message: MessageQueueMessage): Promise { + return this.adapter.publish(topic, message); + } + + subscribe( + topic: string, + listener: MessageQueueListener, + options?: MessageQueueSubscriptionOptions, + ): Promise { + return this.adapter.subscribe(topic, listener, options); + } +} diff --git a/twake/backend/node/src/core/platform/services/message-queue/local/index.ts b/twake/backend/node/src/core/platform/services/message-queue/local/index.ts new file mode 100644 index 0000000000..1eb4cdfdd9 --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/local/index.ts @@ -0,0 +1,97 @@ +import { Subject } from "rxjs"; +import { logger as rootLogger } from "../../../framework/logger"; +import { + IncomingMessageQueueMessage, + MessageQueueAdapter, + MessageQueueListener, + MessageQueueMessage, + MessageQueueSubscriptionOptions, +} from "../api"; +import MessageQueueProxy from "../proxy"; + +const logger = rootLogger.child({ + component: "twake.core.platform.services.message-queue.local", +}); + +/** + * A message-queue service implementation based on RXJS. + */ +export class LocalMessageQueueService implements MessageQueueAdapter { + private subjects: Map>>; + private clientProxy: MessageQueueProxy; + type: "local"; + + constructor() { + this.subjects = new Map>>(); + this.clientProxy = new MessageQueueProxy(); + } + + async init(): Promise { + this.clientProxy.setClient({ + publish: async (topic: string, message: MessageQueueMessage): Promise => { + return this.doPublish(topic, message); + }, + subscribe: async (topic: string, listener: MessageQueueListener): Promise => { + return this.doSubscribe(topic, listener); + }, + async close(): Promise { + logger.info("Closing the local message-queue"); + return this; + }, + }); + + return this; + } + + async stop(): Promise { + logger.info("Closing message-queue service"); + await this.clientProxy.close(); + return this; + } + + async subscribe(topic: string, listener: MessageQueueListener): Promise { + return this.clientProxy.subscribe(topic, listener); + } + + async publish(topic: string, message: MessageQueueMessage): Promise { + return this.clientProxy.publish(topic, message); + } + + private async doSubscribe( + topic: string, + listener: MessageQueueListener, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _options?: MessageQueueSubscriptionOptions, + ): Promise { + if (!this.subjects.has(topic)) { + this.subjects.set(topic, new Subject>()); + } + + this.subjects.get(topic).subscribe({ + next: (value: IncomingMessageQueueMessage) => { + logger.debug("Got a new value to dispatch to topic '%s': %o", topic, value); + try { + listener(value); + } catch (err) { + logger.warn({ err }, "Error while calling listener"); + } + }, + }); + } + + private async doPublish(topic: string, message: MessageQueueMessage): Promise { + if (!this.subjects.has(topic)) { + return; + } + + logger.debug("Publish new value to topic '%s': %o", topic, message); + this.subjects.get(topic)?.next({ + ...message, + ...{ + ack: () => { + logger.debug("ACK message %o", message); + }, + }, + }); + } +} diff --git a/twake/backend/node/src/core/platform/services/message-queue/processor.ts b/twake/backend/node/src/core/platform/services/message-queue/processor.ts new file mode 100644 index 0000000000..3fbd55c72d --- /dev/null +++ b/twake/backend/node/src/core/platform/services/message-queue/processor.ts @@ -0,0 +1,87 @@ +import { logger } from "../../framework"; +import { MessageQueueHandler, MessageQueueServiceAPI, MessageQueueServiceProcessor } from "./api"; + +const LOG_PREFIX = "service.message-queue.Processor"; + +export class Processor { + // TODO: Add state + private registry: ProcessorRegistry; + private started = false; + + constructor(private messageQueue: MessageQueueServiceAPI) { + this.registry = new ProcessorRegistry(this.messageQueue); + } + + async init(): Promise { + return this; + } + + async start(): Promise { + this.started = true; + await Promise.all( + Array.from(this.registry.processors.keys()).map(async name => { + logger.info(`${LOG_PREFIX} - Starting notification processor ${name}`); + await this.registry.processors.get(name)?.init(); + logger.info(`${LOG_PREFIX} - notification processor ${name} is started`); + }), + ); + } + + async stop(): Promise { + this.started = false; + await Promise.all( + Array.from(this.registry.processors.keys()).map(async name => { + this.removeHandler(name); + }), + ); + } + + addHandler(handler: MessageQueueHandler): void { + if (!handler) { + throw new Error(`${LOG_PREFIX} - Can not add null handler`); + } + + logger.info(`${LOG_PREFIX} - Adding message-queue handler ${handler.name}`); + this.registry.register(handler); + + if (this.started) { + this.startHandler(handler.name); + } + } + + async startHandler(name: string): Promise { + logger.info(`${LOG_PREFIX} - Starting message-queue handler ${name}`); + await this.registry.processors.get(name)?.init(); + } + + stopHandler(name: string): void { + logger.info(`${LOG_PREFIX} - Stopping message-queue handler ${name}`); + this.registry.processors.get(name)?.stop(); + } + + removeHandler(name: string): void { + logger.info(`${LOG_PREFIX} - Removing message-queue handler ${name}`); + this.stopHandler(name); + this.registry.processors.delete(name); + } +} + +class ProcessorRegistry { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + processors: Map>; + + constructor(private messageQueue: MessageQueueServiceAPI) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.processors = new Map>(); + } + + register(handler: MessageQueueHandler): void { + if (!handler) { + throw new Error("Can not add a null handler"); + } + this.processors.set( + handler.name, + new MessageQueueServiceProcessor(handler, this.messageQueue), + ); + } +} diff --git a/twake/backend/node/src/core/platform/services/pubsub/proxy.ts b/twake/backend/node/src/core/platform/services/message-queue/proxy.ts similarity index 77% rename from twake/backend/node/src/core/platform/services/pubsub/proxy.ts rename to twake/backend/node/src/core/platform/services/message-queue/proxy.ts index 66488faec9..1b6ffe8f1b 100644 --- a/twake/backend/node/src/core/platform/services/pubsub/proxy.ts +++ b/twake/backend/node/src/core/platform/services/message-queue/proxy.ts @@ -1,31 +1,31 @@ import { isEqual } from "lodash"; import { logger } from "../../framework"; import { - PubsubClient, - PubsubListener, - PubsubMessage, - PubsubProxy, - PubsubSubscriptionOptions, + MessageQueueClient, + MessageQueueListener, + MessageQueueMessage, + MessageQueueProxy, + MessageQueueSubscriptionOptions, } from "./api"; -const LOG_PREFIX = "service.pubsub.PubsubProxyService -"; +const LOG_PREFIX = "service.message-queue.MessageQueueProxyService -"; type ListenerCache = { - listener: PubsubListener; - options?: PubsubSubscriptionOptions; + listener: MessageQueueListener; + options?: MessageQueueSubscriptionOptions; }; /** - * The pubsub implementation managing underlaying pubsub layer mainly used to cache messages and subscriptions when layer is not ready. + * The message-queue implementation managing underlaying message-queue layer mainly used to cache messages and subscriptions when layer is not ready. */ -export default class PubsubProxyService implements PubsubProxy { +export default class MessageQueueProxyService implements MessageQueueProxy { version: "1"; /** * Cache messages to be published to topic when layer is not ready * TODO: We may explode if we can not publish it accumulating messages, add a FIFO with limited size, or cache eviction system... */ // eslint-disable-next-line @typescript-eslint/no-explicit-any - protected publicationsBuffer: Array<{ topic: string; message: PubsubMessage }> = []; + protected publicationsBuffer: Array<{ topic: string; message: MessageQueueMessage }> = []; /** * Cache subscriptions to be created until a new client is set */ @@ -37,10 +37,10 @@ export default class PubsubProxyService implements PubsubProxy { /** * @param client optional initial client */ - constructor(private client?: PubsubClient) {} + constructor(private client?: MessageQueueClient) {} - async setClient(client: PubsubClient): Promise { - logger.info(`${LOG_PREFIX} Setting new pubsub client`); + async setClient(client: MessageQueueClient): Promise { + logger.info(`${LOG_PREFIX} Setting new message-queue client`); // TODO: The client can be removed or replaced while we are looping here // We may wait until things are done, or discard some... if (!client) { @@ -48,7 +48,7 @@ export default class PubsubProxyService implements PubsubProxy { } if (this.client) { - logger.info(`${LOG_PREFIX} Pubsub client already set. Overriding`); + logger.info(`${LOG_PREFIX} MessageQueue client already set. Overriding`); } this.client = client; @@ -101,11 +101,11 @@ export default class PubsubProxyService implements PubsubProxy { try { await this.client?.close?.(); } catch (err) { - logger.debug({ err }, `${LOG_PREFIX} Error on closing the pubsub layer`); + logger.debug({ err }, `${LOG_PREFIX} Error on closing the message-queue layer`); } } - publish(topic: string, message: PubsubMessage): Promise { + publish(topic: string, message: MessageQueueMessage): Promise { if (!this.client) { this.addPublishCache(topic, message); @@ -117,8 +117,8 @@ export default class PubsubProxyService implements PubsubProxy { subscribe( topic: string, - listener: PubsubListener, - options?: PubsubSubscriptionOptions, + listener: MessageQueueListener, + options?: MessageQueueSubscriptionOptions, ): Promise { this.addSubscriptionToCache(topic, listener, options); @@ -131,8 +131,8 @@ export default class PubsubProxyService implements PubsubProxy { private addSubscriptionToCache( topic: string, - listener: PubsubListener, - options: PubsubSubscriptionOptions, + listener: MessageQueueListener, + options: MessageQueueSubscriptionOptions, ): void { if (!this.subscriptionsCache.get(topic)) { this.subscriptionsCache.set(topic, new Set()); @@ -163,8 +163,8 @@ export default class PubsubProxyService implements PubsubProxy { private subscribeToClient( topic: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any - listener: PubsubListener, - options?: PubsubSubscriptionOptions, + listener: MessageQueueListener, + options?: MessageQueueSubscriptionOptions, ): Promise { logger.debug(`${LOG_PREFIX} Trying to subscribe to ${topic} topic with options %o`, options); return this.client?.subscribe(topic, listener, options); diff --git a/twake/backend/node/src/core/platform/services/phpnode/index.ts b/twake/backend/node/src/core/platform/services/phpnode/index.ts index 168ebc7204..ae5c098f4c 100644 --- a/twake/backend/node/src/core/platform/services/phpnode/index.ts +++ b/twake/backend/node/src/core/platform/services/phpnode/index.ts @@ -10,14 +10,12 @@ import { ChannelParameters, CreateChannelBody, } from "../../../../services/channels/web/types"; -import ChannelServiceAPI from "../../../../services/channels/provider"; import { Consumes, TwakeService } from "../../framework"; import WebServerAPI from "../webserver/provider"; import WebSocketAPI from "../websocket/provider"; import PhpNodeAPI from "./provider"; import { RealtimeServiceAPI } from "../realtime/api"; -import { UsersCrudController } from "../../../../services/user/web/controller"; -import UserServiceAPI from "../../../../services/user/api"; +import gr from "../../../../services/global-resolver"; @Consumes(["webserver", "websocket", "user", "channels"]) export default class PhpNodeService extends TwakeService implements PhpNodeAPI { @@ -25,8 +23,6 @@ export default class PhpNodeService extends TwakeService implements version = "1"; private server: FastifyInstance; private ws: WebSocketAPI; - private channels: ChannelServiceAPI; - private users: UserServiceAPI; private realtime: RealtimeServiceAPI; api(): PhpNodeAPI { @@ -72,8 +68,6 @@ export default class PhpNodeService extends TwakeService implements } async doStart(): Promise { - this.channels = this.context.getProvider("channels"); - this.users = this.context.getProvider("user"); return this; } @@ -104,14 +98,11 @@ export default class PhpNodeService extends TwakeService implements method: "GET", url: "/companies/:company_id/workspaces/:workspace_id/channels/:id/members/:member_id/exists", handler: (request: FastifyRequest<{ Params: ChannelMemberParameters }>, reply) => { - if (!this.channels) { + if (!gr.services) { reply.code(500).send(); //Server is not ready return; } - const membersController = new ChannelMemberCrudController( - this.realtime, - this.channels.members, - ); + const membersController = new ChannelMemberCrudController(); membersController.exists(request, reply); }, }); @@ -123,16 +114,11 @@ export default class PhpNodeService extends TwakeService implements method: "GET", url: "/companies/:company_id/workspaces/:workspace_id/channels/:id", handler: (request: FastifyRequest<{ Params: ChannelParameters }>, reply) => { - if (!this.channels) { + if (!gr.services) { reply.code(500).send(); //Server is not ready return; } - const channelsController = new ChannelCrudController( - this.realtime, - this.channels.channels, - this.channels.members, - this.channels.pendingEmails, - ); + const channelsController = new ChannelCrudController(); channelsController.getForPHP(request, reply); }, }); @@ -147,18 +133,21 @@ export default class PhpNodeService extends TwakeService implements request: FastifyRequest<{ Params: { company_id: string; id: string } }>, reply, ) => { - if (!this.channels) { + if (!gr.services) { reply.code(500).send(); //Server is not ready return; } - const workspaces = await this.users.workspaces.getAllForCompany(request.params.company_id); + const workspaces = await gr.services.workspaces.getAllForCompany(request.params.company_id); for (const w of workspaces) { - const channel = await this.channels.channels.get({ - company_id: request.params.company_id, - workspace_id: w.id, - id: request.params.id, - }); + const channel = await gr.services.channels.channels.get( + { + company_id: request.params.company_id, + workspace_id: w.id, + id: request.params.id, + }, + undefined, + ); if (channel) { reply.send(channel); return; @@ -183,16 +172,11 @@ export default class PhpNodeService extends TwakeService implements }>, reply, ) => { - if (!this.channels) { + if (!gr.services) { reply.code(500).send(); //Server is not ready return; } - const channelsController = new ChannelCrudController( - this.realtime, - this.channels.channels, - this.channels.members, - this.channels.pendingEmails, - ); + const channelsController = new ChannelCrudController(); request.currentUser = { id: (request.body as any).user_id, }; diff --git a/twake/backend/node/src/core/platform/services/platform-services/index.ts b/twake/backend/node/src/core/platform/services/platform-services/index.ts deleted file mode 100644 index b323a1cb33..0000000000 --- a/twake/backend/node/src/core/platform/services/platform-services/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { - Consumes, - Initializable, - ServiceName, - TwakeService, - TwakeServiceProvider, -} from "../../framework"; -import WebServerAPI from "../webserver/provider"; -import { DatabaseServiceAPI } from "../database/api"; -import { SearchServiceAPI } from "../search/api"; -import { PubsubServiceAPI } from "../pubsub/api"; -import StorageAPI from "../storage/provider"; -import { CounterAPI } from "../counter/types"; - -export interface PlatformServicesAPI extends TwakeServiceProvider, Initializable { - fastify: WebServerAPI; - database: DatabaseServiceAPI; - search: SearchServiceAPI; - storage: StorageAPI; - pubsub: PubsubServiceAPI; - counter: CounterAPI; -} - -@ServiceName("platform-services") -@Consumes(["webserver", "database", "search", "storage", "pubsub", "counter"]) -export default class PlatformService extends TwakeService { - version = "1"; - name = "platform-services"; - - public fastify: WebServerAPI; - public database: DatabaseServiceAPI; - public search: SearchServiceAPI; - public storage: StorageAPI; - public pubsub: PubsubServiceAPI; - public counter: CounterAPI; - - public async doInit(): Promise { - this.fastify = this.context.getProvider("webserver"); - this.database = this.context.getProvider("database"); - this.search = this.context.getProvider("search"); - this.storage = this.context.getProvider("storage"); - this.pubsub = this.context.getProvider("pubsub"); - this.counter = this.context.getProvider("counter"); - return this; - } - - api(): PlatformServicesAPI { - return this; - } -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/index.ts b/twake/backend/node/src/core/platform/services/pubsub/amqp/index.ts deleted file mode 100644 index e0a7916155..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { Subscription } from "rxjs"; -import { logger as rootLogger } from "../../../framework/logger"; -import { - PubsubAdapter, - PubsubClient, - PubsubListener, - PubsubMessage, - PubsubSubscriptionOptions, -} from "../api"; -import PubsubProxy from "../proxy"; -import { AMQPPubsubManager } from "./manager"; -import { SkipCLI } from "../../../framework/decorators/skip"; - -const logger = rootLogger.child({ - component: "twake.core.platform.services.pubsub.amqp", -}); - -export class AMQPPubsubService implements PubsubAdapter { - version: "1"; - clientProxy: PubsubProxy; - availableSubscription: Subscription; - unavailableSubscription: Subscription; - manager: AMQPPubsubManager; - type: "amqp"; - - constructor(private urls: string[]) { - this.manager = new AMQPPubsubManager(); - this.clientProxy = new PubsubProxy(); - } - - @SkipCLI() - async init(): Promise { - logger.info("Initializing pubsub service implementation with urls %o", this.urls); - await this.manager.createClient(this.urls); - - this.availableSubscription = this.manager.getClientAvailable().subscribe({ - next: (client: PubsubClient) => { - logger.info("A new pubsub client is available"); - this.clientProxy.setClient(client); - }, - error: () => { - logger.error("Error while listening to pubsub client availability"); - }, - }); - - this.unavailableSubscription = this.manager.getClientUnavailable().subscribe({ - next: (err: Error) => { - logger.warn({ err }, "Client is not available anymore"); - this.clientProxy.unsetClient(); - }, - error: () => { - logger.error("Error while listening to pubsub client unavailability"); - }, - }); - - return this; - } - - async stop(): Promise { - logger.info("Closing pubsub service"); - await this.clientProxy.close(); - return this; - } - - publish(topic: string, message: PubsubMessage): Promise { - return this.clientProxy.publish(topic, message); - } - - subscribe( - topic: string, - listener: PubsubListener, - options?: PubsubSubscriptionOptions, - ): Promise { - return this.clientProxy.subscribe(topic, listener, options); - } -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/amqp/pubsub.ts b/twake/backend/node/src/core/platform/services/pubsub/amqp/pubsub.ts deleted file mode 100644 index ee261efa3f..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/amqp/pubsub.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { logger } from "../../../framework/logger"; -import { AmqpPubsubClient } from "./pubsubclient"; -import { PubsubMessage, PubsubListener, PubsubClient, PubsubSubscriptionOptions } from "../api"; -import { AmqpCallbackType, SubscribeOptions } from "./client"; - -const LOG_PREFIX = "service.pubsub.amqp.AMQPPubSub -"; - -/** - * Implementation of PubsubClient based on AMQP - */ -export class AMQPPubSub implements PubsubClient { - constructor(private client: AmqpPubsubClient) {} - - close(): Promise { - return this.client.dispose(); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - async publish(topic: string, message: PubsubMessage): Promise { - logger.debug(`${LOG_PREFIX} Publishing message to topic ${topic}`); - await this.client.publish(topic, message.data, { ttl: message.ttl }); - } - - subscribe( - topic: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - listener: PubsubListener, - options: PubsubSubscriptionOptions = { unique: false, queue: null, ttl: -1 }, - ): Promise { - const subscribeOptions: SubscribeOptions = {}; - logger.debug(`${LOG_PREFIX} Subscribing to topic ${topic} with options %o`, options); - - const callback: AmqpCallbackType = (err, message, originalMessage) => { - const data = err ? originalMessage : message; - - if (err) { - logger.error(`${LOG_PREFIX} Received a message which can not be parsed on topic ${topic}: %o`, originalMessage?.content.toString()); - } - - listener({ - data, - ack: (): void => { - logger.debug(`${LOG_PREFIX} Ack message on topic ${topic}`); - this.client.ack(originalMessage); - }, - }); - }; - - if (options.ttl && options.ttl > 0) { - subscribeOptions.ttl = options.ttl; - } - - return options?.unique - ? this.client.subscribeToDurableQueue(topic, options?.queue || topic, subscribeOptions, callback) - : this.client.subscribe(topic, subscribeOptions, callback); - } -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/api.ts b/twake/backend/node/src/core/platform/services/pubsub/api.ts deleted file mode 100644 index da43faf125..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/api.ts +++ /dev/null @@ -1,322 +0,0 @@ -import { Subject } from "rxjs"; -import { v4 as uuidv4 } from "uuid"; -import { Initializable, logger, TwakeServiceProvider } from "../../framework"; -import { Processor } from "./processor"; - -export type PubsubType = "local" | "amqp"; - -export interface PubsubMessage { - /** - * Optional message id, mainly used for logs - */ - id?: string; - - /** - * The message TTL period in milliseconds - */ - ttl?: number; - - /** - * The message payload to process - */ - data: T; -} - -export interface PubsubEventMessage extends PubsubMessage { - topic: string; -} - -export interface IncomingPubsubMessage extends PubsubMessage { - ack: () => void; -} - -export type PubsubSubscriptionOptions = { - /** - * A unique subscription guaranties that there will be only one listener consuming the message on the subscription topic even if many are subscribing to the same topic from several places (not only from the current instance/host). - * Also, it will guaranties that messages which were published before any subscriber subscribes will be consumed. - */ - unique?: boolean; - - /** - * Automatically acknowledge the incoming message when the processing is complete - */ - ack?: boolean; - - /** - * Use custom named queue instead of using same name as exchange. Can be useful when we have multiple subsciptions on the same topic. - */ - queue?: string | null; - - /** - * Configures the message TTL (in ms) in the underlying messaging system. - * Negative or undefined means no TTL. - * Notes: - * - If supported by the messaging system, messages will not be delivered to the application. - * - If not supported, this may be up to the subscriber itself to filter messages at the application level based on some timestamp if available. - */ - ttl?: number | null; -}; - -export type PubsubListener = (message: IncomingPubsubMessage) => void; - -export interface PubsubServiceAPI extends TwakeServiceProvider { - /** - * Publish a message to a given topic - * @param topic The topic to publish the message to - * @param message The message to publish to the topic - */ - publish(topic: string, message: PubsubMessage): Promise; - - /** - * Subscribe the a topic. The listener will be called when a new message is published in the topic (this may not be true based on the options parameters). - * @param topic The topic to subsribe to - * @param listener The function which will process the message published in the topic - * @param options The subscription options. If not defined, the subscriber will be called for all messages available in the topic. - */ - subscribe( - topic: string, - listener: PubsubListener, - options?: PubsubSubscriptionOptions, - ): Promise; - - /** - * The messages processor instance - */ - processor: Processor; - - stop(): Promise; - start(): Promise; -} - -export type PubsubAdapter = Pick & { - type: string; - init?(): Promise; - start?(): Promise; - stop?(): Promise; -}; - -export type PubsubClient = Pick & { - /** - * Close the client - */ - close?(): Promise; -}; - -/** - * The client manager allows to get notified when a client is available and then becomes unavailable. - */ -export interface PubsubClientManager { - /** - * Ask for a new client to be created - */ - createClient(config: string[]): Promise>; - - /** - * Subject when a client is available - */ - getClientAvailable(): Subject; - - /** - * Subject when a client becomes unavailable - */ - getClientUnavailable(): Subject; -} - -/** - * Manages the pubsub client adding mechanisms to cache subscriptions and messages to publish. - */ -export interface PubsubProxy extends PubsubClient { - /** - * Set a new client to use replacing any existing one. - * The new client will reuse all the subscriptions automatically. - * @param client - */ - setClient(client: PubsubClient): Promise; - - /** - * Remove the client. This will close any underlying connection but will not remove any subscription. - */ - unsetClient(): Promise; -} - -export interface PubsubEventBus { - /** - * Subscribes to events - */ - subscribe(listener: (message: PubsubEventMessage) => void): this; - - /** - * Publish message in event bus - */ - publish(message: PubsubEventMessage): boolean; -} - -export abstract class PubsubServiceSubscription { - protected pubsub: PubsubServiceAPI; - - async subscribe(pubsub: PubsubServiceAPI): Promise { - if (!pubsub) { - throw new Error("pubsub service it not defined"); - } - this.pubsub = pubsub; - - return this.doSubscribe(); - } - - abstract doSubscribe(): Promise; -} - -export class PubsubServiceProcessor - extends PubsubServiceSubscription - implements Initializable -{ - constructor(protected handler: PubsubHandler, protected pubsub: PubsubServiceAPI) { - super(); - } - - async init(): Promise { - try { - await this.subscribe(this.pubsub); - } catch (err) { - logger.warn( - { err }, - `PubsubServiceProcessor.handler.${this.handler.name} - Not able to start handler`, - ); - } - - return this; - } - - async stop(): Promise { - // TODO - return this; - } - - async process(message: IncomingPubsubMessage): Promise { - logger.info( - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Processing message`, - ); - return this.handler.process(message.data); - } - - async doSubscribe(): Promise { - if (this.handler.topics && this.handler.topics.in) { - logger.info( - `PubsubServiceProcessor.handler.${this.handler.name} - Subscribing to topic ${this.handler?.topics?.in} with options %o`, - this.handler.options, - ); - await this.pubsub.subscribe( - this.handler.topics.in, - this.processMessage.bind(this), - this.handler.options, - ); - } - } - - private async processMessage(message: IncomingPubsubMessage): Promise { - if (!message.id) { - message.id = uuidv4(); - } - - if (this.handler.validate) { - const isValid = this.handler.validate(message.data); - - if (!isValid) { - logger.error( - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Message is invalid`, - ); - - return; - } - } - - try { - const result = await this.process(message); - if (this.handler?.options?.ack) { - logger.debug( - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Acknowledging message %o`, - message, - ); - message?.ack(); - } - - if (result) { - await this.sendResult(message, result); - } - } catch (error) { - this.handleError(message, error); - } - } - - private async sendResult(message: IncomingPubsubMessage, result: Out): Promise { - if (!this.handler.topics.out) { - logger.info( - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Message processing result is skipped`, - ); - return; - } - - logger.info( - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Sending processing result to ${this.handler.topics.out}`, - ); - - return this.pubsub.publish(this.handler.topics.out, { - id: uuidv4(), - data: result, - }); - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - private async handleError(message: IncomingPubsubMessage, err: any) { - logger.error( - { err }, - `PubsubServiceProcessor.handler.${this.handler.name}:${message.id} - Error while processing message`, - ); - if (this.handler.topics.error) { - this.pubsub.publish(this.handler.topics.error, { - data: { - type: "error", - id: message.id, - message: err instanceof Error ? (err as Error).message : String(err), - }, - }); - } - } -} - -/** - * A pubsub handler is in charge of processing message from a topic and publishing the processing result to another topic - */ -export interface PubsubHandler extends Initializable { - readonly topics: { - // The topic to subscribe to - in: string; - // The topic to push process result to if defined - out?: string; - // The topic to push error to. When topic is undefined, do not push the error - error?: string; - }; - - /** - * Options subscriber options - */ - readonly options?: PubsubSubscriptionOptions; - - /** - * The handler name - */ - readonly name: string; - - /** - * Validate the input message - * - * @param message message to validate - */ - validate?(message: InputMessage): boolean; - - /** - * Process the message and potentially produces result which will be published elsewhere - * @param message - */ - process(message: InputMessage): Promise; -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/bus.ts b/twake/backend/node/src/core/platform/services/pubsub/bus.ts deleted file mode 100644 index f2025b5c35..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/bus.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { EventEmitter } from "events"; -import { PubsubEventBus, PubsubEventMessage } from "./api"; -const EVENT = Symbol("event"); - -/** - * Event bus is used by the Pubsub decorators to publish data to be send to pubsub service. - * The pubsub service is the only subscriber of the event bus. - * By decoupling decorator and service, events will not be published when the service is not enabled. - */ -class EventBus extends EventEmitter implements PubsubEventBus { - constructor() { - super(); - } - - /** - * Subscribe is MUST only be used by the pubsub service - * - * @param listener - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - subscribe(listener: (message: PubsubEventMessage) => void): this { - return this.on(EVENT, listener); - } - - /** - * Publish must only be used by the Pubsub decorators - * - * @param message - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - publish(message: PubsubEventMessage): boolean { - return this.emit(EVENT, message); - } -} - -export const eventBus = new EventBus(); diff --git a/twake/backend/node/src/core/platform/services/pubsub/decorators/publish.ts b/twake/backend/node/src/core/platform/services/pubsub/decorators/publish.ts deleted file mode 100644 index 4a12206485..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/decorators/publish.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { eventBus } from "../bus"; - -/* eslint-disable @typescript-eslint/no-explicit-any */ -const METADATA_NAME = "pubsub:parameter"; - -/** - * Methods decorated with this decorator will publish message defined by the PubsubParameter annotated parameters - * - * @param topic The topic to push the data to - * @param data The default data to publish in the topic. This message will be enriched and overrided by the @PubsubParameter values - */ -export function PubsubPublish(topic: string, data: { [id: string]: any } = {}): MethodDecorator { - // eslint-disable-next-line @typescript-eslint/ban-types - return function (target: Object, propertyKey: string, descriptor: PropertyDescriptor): void { - const fields: Map = - Reflect.getOwnMetadata(`${METADATA_NAME}:${String(propertyKey)}`, target) || - new Map(); - - if (fields.size === 0) { - return; - } - - const originalMethod = descriptor.value; - - descriptor.value = async function (...args: any[]) { - fields.forEach((value, index) => { - data[value] = args[index]; - }); - - eventBus.publish({ - data, - topic, - }); - - return await originalMethod.apply(this, args); - }; - }; -} - -/** - * Defines parameters of the function to be used as pubsub message data - * - * @param parameterName the name to be used as property name in the pubsub message data - */ -export function PubsubParameter(parameterName: string): ParameterDecorator { - // eslint-disable-next-line @typescript-eslint/ban-types - return function (target: Object, propertyKey: string | symbol, parameterIndex: number): void { - const fields: Map = - Reflect.getOwnMetadata(`${METADATA_NAME}:${String(propertyKey)}`, target) || - new Map(); - - fields.set(parameterIndex, parameterName); - Reflect.defineMetadata(`${METADATA_NAME}:${String(propertyKey)}`, fields, target); - }; -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/factory.ts b/twake/backend/node/src/core/platform/services/pubsub/factory.ts deleted file mode 100644 index ca7026d834..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/factory.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { PubsubAdapter, PubsubType } from "./api"; -import { AMQPPubsubService } from "./amqp"; -import { LocalPubsubService } from "./local"; -import { TwakeServiceConfiguration, logger as rootLogger } from "../../framework"; - -const logger = rootLogger.child({ - component: "twake.core.platform.services.pubsub.factory", -}); - -const DEFAULT_AMQP_URL = "amqp://guest:guest@localhost:5672"; -const DEFAULT_ADAPTER = "amqp"; - -export class PubsubAdapterFactory { - public create(configuration: TwakeServiceConfiguration): PubsubAdapter { - const type: PubsubType = configuration.get("type", DEFAULT_ADAPTER); - - logger.info("Building Adapter %o", type); - - switch (type) { - case "local": - return new LocalPubsubService(); - case "amqp": - let urls: string[] = configuration.get("amqp.urls", [DEFAULT_AMQP_URL]); - - //For environment variables - if (typeof urls === "string") { - urls = (urls as string).split(","); - } - - return new AMQPPubsubService(urls); - default: - logger.error("Adapter '%o' is not supported", type); - throw new Error(`${type} is not supported`); - } - } -} - -export default new PubsubAdapterFactory(); diff --git a/twake/backend/node/src/core/platform/services/pubsub/index.ts b/twake/backend/node/src/core/platform/services/pubsub/index.ts deleted file mode 100644 index e61631a5b7..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { TwakeService, ServiceName, logger as rootLogger } from "../../framework"; -import { - PubsubAdapter, - PubsubListener, - PubsubMessage, - PubsubServiceAPI, - PubsubSubscriptionOptions, -} from "./api"; -import { eventBus } from "./bus"; -import { Processor } from "./processor"; -import adapterFactory from "./factory"; -import { SkipCLI } from "../../framework/decorators/skip"; - -const logger = rootLogger.child({ - component: "twake.core.platform.services.pubsub", -}); -@ServiceName("pubsub") -export default class Pubsub extends TwakeService { - version = "1"; - name = "pubsub"; - service: PubsubService; - - async doInit(): Promise { - this.service = new PubsubService(adapterFactory.create(this.configuration)); - await this.service.init(); - - eventBus.subscribe(message => { - logger.info(`Event bus publishing message to ${message.topic}`); - this.service.publish(message.topic, { data: message.data }); - }); - - return this; - } - - async doStart(): Promise { - await this.service.start(); - - return this; - } - - async doStop(): Promise { - await this.service.stop(); - - return this; - } - - api(): PubsubServiceAPI { - return this.service; - } -} - -export class PubsubService implements PubsubServiceAPI { - version: "1"; - processor: Processor; - - constructor(private adapter: PubsubAdapter) { - this.processor = new Processor(this); - } - - @SkipCLI() - async init(): Promise { - logger.info("Initializing pubsub adapter %o", this.adapter.type); - await this.adapter?.init?.(); - - return this; - } - - @SkipCLI() - async start(): Promise { - logger.info("Starting pubsub adapter %o", this.adapter.type); - await this.adapter?.start?.(); - await this.processor.start(); - - return this; - } - - @SkipCLI() - async stop(): Promise { - logger.info("Stopping pubsub adapter %o", this.adapter.type); - await this.adapter?.stop?.(); - await this.processor.stop(); - - return this; - } - - publish(topic: string, message: PubsubMessage): Promise { - return this.adapter.publish(topic, message); - } - - subscribe( - topic: string, - listener: PubsubListener, - options?: PubsubSubscriptionOptions, - ): Promise { - return this.adapter.subscribe(topic, listener, options); - } -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/local/index.ts b/twake/backend/node/src/core/platform/services/pubsub/local/index.ts deleted file mode 100644 index 57c7d58d48..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/local/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { Subject } from "rxjs"; -import { logger as rootLogger } from "../../../framework/logger"; -import { - IncomingPubsubMessage, - PubsubAdapter, - PubsubListener, - PubsubMessage, - PubsubSubscriptionOptions, -} from "../api"; -import PubsubProxy from "../proxy"; - -const logger = rootLogger.child({ - component: "twake.core.platform.services.pubsub.local", -}); - -/** - * A pubsub service implementation based on RXJS. - */ -export class LocalPubsubService implements PubsubAdapter { - private subjects: Map>>; - private clientProxy: PubsubProxy; - type: "local"; - - constructor() { - this.subjects = new Map>>(); - this.clientProxy = new PubsubProxy(); - } - - async init(): Promise { - this.clientProxy.setClient({ - publish: async (topic: string, message: PubsubMessage): Promise => { - return this.doPublish(topic, message); - }, - subscribe: async (topic: string, listener: PubsubListener): Promise => { - return this.doSubscribe(topic, listener); - }, - async close(): Promise { - logger.info("Closing the local pubsub"); - return this; - }, - }); - - return this; - } - - async stop(): Promise { - logger.info("Closing pubsub service"); - await this.clientProxy.close(); - return this; - } - - async subscribe(topic: string, listener: PubsubListener): Promise { - return this.clientProxy.subscribe(topic, listener); - } - - async publish(topic: string, message: PubsubMessage): Promise { - return this.clientProxy.publish(topic, message); - } - - private async doSubscribe( - topic: string, - listener: PubsubListener, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _options?: PubsubSubscriptionOptions, - ): Promise { - if (!this.subjects.has(topic)) { - this.subjects.set(topic, new Subject>()); - } - - this.subjects.get(topic).subscribe({ - next: (value: IncomingPubsubMessage) => { - logger.debug("Got a new value to dispatch to topic '%s': %o", topic, value); - try { - listener(value); - } catch (err) { - logger.warn({ err }, "Error while calling listener"); - } - }, - }); - } - - private async doPublish(topic: string, message: PubsubMessage): Promise { - if (!this.subjects.has(topic)) { - return; - } - - logger.debug("Publish new value to topic '%s': %o", topic, message); - this.subjects.get(topic)?.next({ - ...message, - ...{ - ack: () => { - logger.debug("ACK message %o", message); - }, - }, - }); - } -} diff --git a/twake/backend/node/src/core/platform/services/pubsub/processor.ts b/twake/backend/node/src/core/platform/services/pubsub/processor.ts deleted file mode 100644 index 7c2f4a3db3..0000000000 --- a/twake/backend/node/src/core/platform/services/pubsub/processor.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { logger } from "../../framework"; -import { PubsubHandler, PubsubServiceAPI, PubsubServiceProcessor } from "./api"; - -const LOG_PREFIX = "service.pubsub.Processor"; - -export class Processor { - // TODO: Add state - private registry: ProcessorRegistry; - - constructor(private pubsub: PubsubServiceAPI) { - this.registry = new ProcessorRegistry(this.pubsub); - } - - async init(): Promise { - return this; - } - - async start(): Promise { - await Promise.all( - Array.from(this.registry.processors.keys()).map(async name => { - logger.info(`${LOG_PREFIX} - Starting notification processor ${name}`); - await this.registry.processors.get(name)?.init(); - logger.info(`${LOG_PREFIX} - notification processor ${name} is started`); - }), - ); - } - - async stop(): Promise { - await Promise.all( - Array.from(this.registry.processors.keys()).map(async name => { - this.removeHandler(name); - }), - ); - } - - addHandler(handler: PubsubHandler): void { - // TODO: Start the handler if added when service is already started - if (!handler) { - throw new Error(`${LOG_PREFIX} - Can not add null handler`); - } - - logger.info(`${LOG_PREFIX} - Adding pubsub handler ${handler.name}`); - this.registry.register(handler); - } - - async startHandler(name: string): Promise { - logger.info(`${LOG_PREFIX} - Starting pubsub handler ${name}`); - await this.registry.processors.get(name)?.init(); - } - - stopHandler(name: string): void { - logger.info(`${LOG_PREFIX} - Stopping pubsub handler ${name}`); - this.registry.processors.get(name)?.stop(); - } - - removeHandler(name: string): void { - logger.info(`${LOG_PREFIX} - Removing pubsub handler ${name}`); - this.stopHandler(name); - this.registry.processors.delete(name); - } -} - -class ProcessorRegistry { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - processors: Map>; - - constructor(private pubsub: PubsubServiceAPI) { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - this.processors = new Map>(); - } - - register(handler: PubsubHandler): void { - if (!handler) { - throw new Error("Can not add a null handler"); - } - this.processors.set(handler.name, new PubsubServiceProcessor(handler, this.pubsub)); - } -} diff --git a/twake/backend/node/src/core/platform/services/push/connectors/fcm/service.ts b/twake/backend/node/src/core/platform/services/push/connectors/fcm/service.ts index 5c5d6fe2b6..c4082a60d7 100644 --- a/twake/backend/node/src/core/platform/services/push/connectors/fcm/service.ts +++ b/twake/backend/node/src/core/platform/services/push/connectors/fcm/service.ts @@ -1,8 +1,7 @@ -import { option } from "yargs"; +import fetch from "node-fetch"; import { logger } from "../../../../framework"; import { PushConfiguration, PushMessageNotification, PushMessageOptions } from "../../types"; import { PushConnector } from "../connector"; -import fetch from "node-fetch"; export default class FcmPushConnector implements PushConnector { name = "FcmPushConnector"; @@ -32,12 +31,12 @@ export default class FcmPushConnector implements PushConnector { //Push to fcm try { const response = await fetch(firebaseEndpoint, { + method: "post", + body: JSON.stringify(pushMessage), headers: { "Content-Type": "application/json", Authorization: `key=${firebaseApiKey}`, }, - method: "POST", - body: JSON.stringify(pushMessage), }); if (response.status !== 200) { logger.error(`${this.name} - Reply from FCM status code : ${response.status}`); diff --git a/twake/backend/node/src/core/platform/services/realtime/bus.ts b/twake/backend/node/src/core/platform/services/realtime/bus.ts index 89c70a72e2..1ae54fbdf6 100644 --- a/twake/backend/node/src/core/platform/services/realtime/bus.ts +++ b/twake/backend/node/src/core/platform/services/realtime/bus.ts @@ -5,7 +5,7 @@ import { EventEmitter } from "events"; import { RealtimeEventBus } from "./api"; import { RealtimeEntityEvent } from "./types"; -class EventBus extends EventEmitter implements RealtimeEventBus { +class WebsocketEventBus extends EventEmitter implements RealtimeEventBus { constructor() { super(); } @@ -19,4 +19,4 @@ class EventBus extends EventEmitter implements RealtimeEventBus { } } -export const eventBus = new EventBus(); +export const websocketEventBus = new WebsocketEventBus(); diff --git a/twake/backend/node/src/core/platform/services/realtime/index.ts b/twake/backend/node/src/core/platform/services/realtime/index.ts index 4dafc56861..9cc94ee504 100644 --- a/twake/backend/node/src/core/platform/services/realtime/index.ts +++ b/twake/backend/node/src/core/platform/services/realtime/index.ts @@ -1,13 +1,13 @@ import { Consumes, ServiceName, TwakeService } from "../../framework"; import { SkipCLI } from "../../framework/decorators/skip"; -import { localEventBus } from "../../framework/pubsub"; +import { localEventBus } from "../../framework/event-bus"; import WebSocketAPI from "../../services/websocket/provider"; -import AuthServiceAPI from "../auth/provider"; -import { RealtimeEventBus, RealtimeServiceAPI, RealtimeRoomManager } from "./api"; -import { eventBus } from "./bus"; +import AuthService from "../auth/provider"; +import { RealtimeEventBus, RealtimeRoomManager, RealtimeServiceAPI } from "./api"; +import { websocketEventBus } from "./bus"; import RealtimeEntityManager from "./services/entity-manager"; import RoomManagerImpl from "./services/room-manager"; -import { RealtimeLocalBusEvent } from "./types"; +import { RealtimeBaseBusEvent, RealtimeLocalBusEvent } from "./types"; @Consumes(["websocket", "auth"]) @ServiceName("realtime") @@ -17,7 +17,7 @@ export default class RealtimeService { private roomManager: RoomManagerImpl; private entityManager: RealtimeEntityManager; - private auth: AuthServiceAPI; + private auth: AuthService; version = "1"; api(): RealtimeServiceAPI { @@ -27,13 +27,18 @@ export default class RealtimeService @SkipCLI() async doStart(): Promise { const ws = this.context.getProvider("websocket"); - this.auth = this.context.getProvider("auth"); + this.auth = this.context.getProvider("auth"); this.roomManager = new RoomManagerImpl(ws, this.auth); this.roomManager.init(); this.entityManager = new RealtimeEntityManager(ws); this.entityManager.init(); + localEventBus.subscribe("realtime:event", (event: RealtimeBaseBusEvent) => { + event.data._type = event.type; + ws.getIo().to(event.room).emit("realtime:event", { name: event.room, data: event.data }); + }); + localEventBus.subscribe("realtime:publish", (data: RealtimeLocalBusEvent) => { this.getBus().publish(data.topic, data.event); }); @@ -42,7 +47,7 @@ export default class RealtimeService } getBus(): RealtimeEventBus { - return eventBus; + return websocketEventBus; } getRoomManager(): RealtimeRoomManager { diff --git a/twake/backend/node/src/core/platform/services/realtime/services/entity-manager.ts b/twake/backend/node/src/core/platform/services/realtime/services/entity-manager.ts index eadca53f17..49c5a14bed 100644 --- a/twake/backend/node/src/core/platform/services/realtime/services/entity-manager.ts +++ b/twake/backend/node/src/core/platform/services/realtime/services/entity-manager.ts @@ -1,7 +1,7 @@ import { logger } from "../../../framework/logger"; import { RealtimeEntityActionType, RealtimeEntityEvent } from "../types"; import WebSocketAPI from "../../../services/websocket/provider"; -import { eventBus } from "../bus"; +import { websocketEventBus } from "../bus"; const REALTIME_RESOURCE = "realtime:resource"; @@ -9,23 +9,23 @@ export default class RealtimeEntityManager { constructor(private ws: WebSocketAPI) {} init(): void { - eventBus.subscribe(RealtimeEntityActionType.Created, event => { + websocketEventBus.subscribe(RealtimeEntityActionType.Created, event => { this.pushResourceEvent(event, RealtimeEntityActionType.Created); }); - eventBus.subscribe(RealtimeEntityActionType.Updated, event => { + websocketEventBus.subscribe(RealtimeEntityActionType.Updated, event => { this.pushResourceEvent(event, RealtimeEntityActionType.Updated); }); - eventBus.subscribe(RealtimeEntityActionType.Deleted, event => { + websocketEventBus.subscribe(RealtimeEntityActionType.Deleted, event => { this.pushResourceEvent(event, RealtimeEntityActionType.Deleted); }); - eventBus.subscribe(RealtimeEntityActionType.Saved, event => { + websocketEventBus.subscribe(RealtimeEntityActionType.Saved, event => { this.pushResourceEvent(event, RealtimeEntityActionType.Saved); }); - eventBus.subscribe(RealtimeEntityActionType.Event, event => { + websocketEventBus.subscribe(RealtimeEntityActionType.Event, event => { this.pushResourceEvent(event, RealtimeEntityActionType.Event); }); } diff --git a/twake/backend/node/src/core/platform/services/realtime/services/room-manager.ts b/twake/backend/node/src/core/platform/services/realtime/services/room-manager.ts index cce5097275..d0a57fb665 100644 --- a/twake/backend/node/src/core/platform/services/realtime/services/room-manager.ts +++ b/twake/backend/node/src/core/platform/services/realtime/services/room-manager.ts @@ -10,10 +10,10 @@ import { import { RealtimeRoomManager } from "../api"; import WebSocketAPI from "../../../services/websocket/provider"; import { WebSocketUser, WebSocket } from "../../../services/websocket/types"; -import AuthServiceAPI from "../../auth/provider"; +import AuthService from "../../auth/provider"; export default class RoomManager implements RealtimeRoomManager { - constructor(private ws: WebSocketAPI, private auth: AuthServiceAPI) {} + constructor(private ws: WebSocketAPI, private auth: AuthService) {} init(): void { this.ws.onUserConnected(event => { @@ -60,8 +60,8 @@ export default class RoomManager implements RealtimeRoomManager { } getConnectedUsers(room: string): number { - if (this.ws.getIo().sockets.adapter.rooms[room]) { - return this.ws.getIo().sockets.adapter.rooms[room].length; + if (this.ws.getIo().sockets.adapter.rooms.has(room)) { + return this.ws.getIo().sockets.adapter.rooms.get(room).entries.length; } return 0; @@ -79,7 +79,7 @@ export default class RoomManager implements RealtimeRoomManager { try { //Public rooms we just check the user is logged in - if (joinEvent.name === "/users/online" || joinEvent.name === "/ping") { + if (joinEvent.name.startsWith("/users/online") || joinEvent.name === "/ping") { return !!this.auth.verifyToken(joinEvent.token)?.sub; } @@ -102,9 +102,12 @@ export default class RoomManager implements RealtimeRoomManager { userCanEmitInRoom = this.userCanJoinRoom; - join(websocket: WebSocket, room: string, user: WebSocketUser): void { + async join(websocket: WebSocket, room: string, user: WebSocketUser): Promise { logger.info(`User ${user.id} is joining room ${room}`); - websocket.join(room, err => { + + try { + await websocket.join(room); + } catch (err) { if (err) { logger.error(`Error while joining room ${room}`, err); this.sendError("join", websocket, { @@ -113,17 +116,18 @@ export default class RoomManager implements RealtimeRoomManager { }); return; } + } - this.sendSuccess("join", websocket, { name: room }); - logger.info(`User ${user.id} joined room ${room}`); - }); + this.sendSuccess("join", websocket, { name: room }); + logger.info(`User ${user.id} joined room ${room}`); } - leave(websocket: WebSocket, room: string, user: WebSocketUser): void { + async leave(websocket: WebSocket, room: string, user: WebSocketUser): Promise { logger.info(`User ${user.id} is leaving room ${room}`); - // eslint-disable-next-line @typescript-eslint/no-explicit-any - websocket.leave(room, (err: any) => { + try { + await websocket.leave(room); + } catch (err) { if (err) { logger.error(`Error while leaving room ${room}`, err); this.sendError("leave", websocket, { @@ -132,15 +136,15 @@ export default class RoomManager implements RealtimeRoomManager { }); return; } + } - this.sendSuccess("leave", websocket, { name: room }); - logger.info(`User ${user.id} left room ${room}`); - }); + this.sendSuccess("leave", websocket, { name: room }); + logger.info(`User ${user.id} left room ${room}`); } leaveAll(websocket: WebSocket, user: WebSocketUser): void { logger.info(`Leaving rooms for user ${user.id}`); - websocket.leaveAll(); + websocket.rooms.forEach(room => websocket.leave(room)); } sendError(event: string, websocket: WebSocket, error: JoinLeaveRoomError): void { diff --git a/twake/backend/node/src/core/platform/services/realtime/types.ts b/twake/backend/node/src/core/platform/services/realtime/types.ts index 02f7eda879..0c65b11120 100644 --- a/twake/backend/node/src/core/platform/services/realtime/types.ts +++ b/twake/backend/node/src/core/platform/services/realtime/types.ts @@ -37,6 +37,20 @@ export class RealtimeEntityEvent { // the action result which fired this event result: EntityOperationResult | null; } + +export class RealtimeApplicationEvent { + action: "configure" | "close_configure"; + application: unknown; + form: unknown; + hidden_data: unknown; +} + +export class RealtimeBaseBusEvent { + room: string; + type: string; + data: T; +} + export class RealtimeLocalBusEvent { event: RealtimeEntityEvent; topic: string; diff --git a/twake/backend/node/src/core/platform/services/search/adapters/abstract.ts b/twake/backend/node/src/core/platform/services/search/adapters/abstract.ts index 9dcf7d8ef5..1dd64b48d5 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/abstract.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/abstract.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-unused-vars */ import { ListResult } from "../../../framework/api/crud-service"; import { FindFilter } from "../../database/services/orm/repository/repository"; import { @@ -9,13 +10,15 @@ import { SearchAdapterInterface, } from "../api"; +type indexColumns = { [name: string]: ColumnDefinition }; + export class SearchAdapter implements SearchAdapterInterface { private createdIndexes: string[] = []; protected async ensureIndex( entityDefinition: EntityDefinition, - columns: { [name: string]: ColumnDefinition }, - createIndex: Function, + columns: indexColumns, + createIndex: (arg0: EntityDefinition, arg1: indexColumns) => any, ) { const index = entityDefinition.name; if (!this.createdIndexes.includes(index)) { diff --git a/twake/backend/node/src/core/platform/services/search/adapters/ascii-folder.ts b/twake/backend/node/src/core/platform/services/search/adapters/ascii-folder.ts new file mode 100644 index 0000000000..060c01d79f --- /dev/null +++ b/twake/backend/node/src/core/platform/services/search/adapters/ascii-folder.ts @@ -0,0 +1,1299 @@ +/** + * ascii-folder.js + * https://github.com/mplatt/fold-to-ascii-js + * + * This is a JavaScript port of the Apache Lucene ASCII Folding Filter. + * + * The Apache Lucene ASCII Folding Filter is licensed to the Apache Software + * Foundation (ASF) under one or more contributor license agreements. See the + * NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache + * License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +class ASCIIFolder { + static foldReplacing(str = "", replacement = "") { + return this._fold(str, () => replacement); + } + + static foldMaintaining(str = "") { + return this._fold(str, (char: string) => char); + } + + static _fold(str: string, fallback: Function) { + if (str === null) return ""; + + if (typeof str === "number") return "" + str; + + if (typeof str !== "string") throw new Error("Invalid input data type"); + + return str + .split("") + .map(character => { + if (character.charCodeAt(0) < 128) { + return character; + } else { + //@ts-ignore + const replacement = this.mapping.get(character.charCodeAt(0)); + return replacement === undefined ? fallback(character) : replacement; + } + }) + .join(""); + } +} + +//@ts-ignore +ASCIIFolder.mapping = new Map([ + [0xc0, "A"], + [0xc1, "A"], + [0xc2, "A"], + [0xc3, "A"], + [0xc4, "A"], + [0xc5, "A"], + [0x100, "A"], + [0x102, "A"], + [0x104, "A"], + [0x18f, "A"], + [0x1cd, "A"], + [0x1de, "A"], + [0x1e0, "A"], + [0x1fa, "A"], + [0x200, "A"], + [0x202, "A"], + [0x226, "A"], + [0x23a, "A"], + [0x1d00, "A"], + [0x1e00, "A"], + [0x1ea0, "A"], + [0x1ea2, "A"], + [0x1ea4, "A"], + [0x1ea6, "A"], + [0x1ea8, "A"], + [0x1eaa, "A"], + [0x1eac, "A"], + [0x1eae, "A"], + [0x1eb0, "A"], + [0x1eb2, "A"], + [0x1eb4, "A"], + [0x1eb6, "A"], + [0x24b6, "A"], + [0xff21, "A"], + [0xe0, "a"], + [0xe1, "a"], + [0xe2, "a"], + [0xe3, "a"], + [0xe4, "a"], + [0xe5, "a"], + [0x101, "a"], + [0x103, "a"], + [0x105, "a"], + [0x1ce, "a"], + [0x1df, "a"], + [0x1e1, "a"], + [0x1fb, "a"], + [0x201, "a"], + [0x203, "a"], + [0x227, "a"], + [0x250, "a"], + [0x259, "a"], + [0x25a, "a"], + [0x1d8f, "a"], + [0x1d95, "a"], + [0x1e01, "a"], + [0x1e9a, "a"], + [0x1ea1, "a"], + [0x1ea3, "a"], + [0x1ea5, "a"], + [0x1ea7, "a"], + [0x1ea9, "a"], + [0x1eab, "a"], + [0x1ead, "a"], + [0x1eaf, "a"], + [0x1eb1, "a"], + [0x1eb3, "a"], + [0x1eb5, "a"], + [0x1eb7, "a"], + [0x2090, "a"], + [0x2094, "a"], + [0x24d0, "a"], + [0x2c65, "a"], + [0x2c6f, "a"], + [0xff41, "a"], + [0xa732, "AA"], + [0xc6, "AE"], + [0x1e2, "AE"], + [0x1fc, "AE"], + [0x1d01, "AE"], + [0xa734, "AO"], + [0xa736, "AU"], + [0xa738, "AV"], + [0xa73a, "AV"], + [0xa73c, "AY"], + [0x249c, "(a)"], + [0xa733, "aa"], + [0xe6, "ae"], + [0x1e3, "ae"], + [0x1fd, "ae"], + [0x1d02, "ae"], + [0xa735, "ao"], + [0xa737, "au"], + [0xa739, "av"], + [0xa73b, "av"], + [0xa73d, "ay"], + [0x181, "B"], + [0x182, "B"], + [0x243, "B"], + [0x299, "B"], + [0x1d03, "B"], + [0x1e02, "B"], + [0x1e04, "B"], + [0x1e06, "B"], + [0x24b7, "B"], + [0xff22, "B"], + [0x180, "b"], + [0x183, "b"], + [0x253, "b"], + [0x1d6c, "b"], + [0x1d80, "b"], + [0x1e03, "b"], + [0x1e05, "b"], + [0x1e07, "b"], + [0x24d1, "b"], + [0xff42, "b"], + [0x249d, "(b)"], + [0xc7, "C"], + [0x106, "C"], + [0x108, "C"], + [0x10a, "C"], + [0x10c, "C"], + [0x187, "C"], + [0x23b, "C"], + [0x297, "C"], + [0x1d04, "C"], + [0x1e08, "C"], + [0x24b8, "C"], + [0xff23, "C"], + [0xe7, "c"], + [0x107, "c"], + [0x109, "c"], + [0x10b, "c"], + [0x10d, "c"], + [0x188, "c"], + [0x23c, "c"], + [0x255, "c"], + [0x1e09, "c"], + [0x2184, "c"], + [0x24d2, "c"], + [0xa73e, "c"], + [0xa73f, "c"], + [0xff43, "c"], + [0x249e, "(c)"], + [0xd0, "D"], + [0x10e, "D"], + [0x110, "D"], + [0x189, "D"], + [0x18a, "D"], + [0x18b, "D"], + [0x1d05, "D"], + [0x1d06, "D"], + [0x1e0a, "D"], + [0x1e0c, "D"], + [0x1e0e, "D"], + [0x1e10, "D"], + [0x1e12, "D"], + [0x24b9, "D"], + [0xa779, "D"], + [0xff24, "D"], + [0xf0, "d"], + [0x10f, "d"], + [0x111, "d"], + [0x18c, "d"], + [0x221, "d"], + [0x256, "d"], + [0x257, "d"], + [0x1d6d, "d"], + [0x1d81, "d"], + [0x1d91, "d"], + [0x1e0b, "d"], + [0x1e0d, "d"], + [0x1e0f, "d"], + [0x1e11, "d"], + [0x1e13, "d"], + [0x24d3, "d"], + [0xa77a, "d"], + [0xff44, "d"], + [0x1c4, "DZ"], + [0x1f1, "DZ"], + [0x1c5, "Dz"], + [0x1f2, "Dz"], + [0x249f, "(d)"], + [0x238, "db"], + [0x1c6, "dz"], + [0x1f3, "dz"], + [0x2a3, "dz"], + [0x2a5, "dz"], + [0xc8, "E"], + [0xc9, "E"], + [0xca, "E"], + [0xcb, "E"], + [0x112, "E"], + [0x114, "E"], + [0x116, "E"], + [0x118, "E"], + [0x11a, "E"], + [0x18e, "E"], + [0x190, "E"], + [0x204, "E"], + [0x206, "E"], + [0x228, "E"], + [0x246, "E"], + [0x1d07, "E"], + [0x1e14, "E"], + [0x1e16, "E"], + [0x1e18, "E"], + [0x1e1a, "E"], + [0x1e1c, "E"], + [0x1eb8, "E"], + [0x1eba, "E"], + [0x1ebc, "E"], + [0x1ebe, "E"], + [0x1ec0, "E"], + [0x1ec2, "E"], + [0x1ec4, "E"], + [0x1ec6, "E"], + [0x24ba, "E"], + [0x2c7b, "E"], + [0xff25, "E"], + [0xe8, "e"], + [0xe9, "e"], + [0xea, "e"], + [0xeb, "e"], + [0x113, "e"], + [0x115, "e"], + [0x117, "e"], + [0x119, "e"], + [0x11b, "e"], + [0x1dd, "e"], + [0x205, "e"], + [0x207, "e"], + [0x229, "e"], + [0x247, "e"], + [0x258, "e"], + [0x25b, "e"], + [0x25c, "e"], + [0x25d, "e"], + [0x25e, "e"], + [0x29a, "e"], + [0x1d08, "e"], + [0x1d92, "e"], + [0x1d93, "e"], + [0x1d94, "e"], + [0x1e15, "e"], + [0x1e17, "e"], + [0x1e19, "e"], + [0x1e1b, "e"], + [0x1e1d, "e"], + [0x1eb9, "e"], + [0x1ebb, "e"], + [0x1ebd, "e"], + [0x1ebf, "e"], + [0x1ec1, "e"], + [0x1ec3, "e"], + [0x1ec5, "e"], + [0x1ec7, "e"], + [0x2091, "e"], + [0x24d4, "e"], + [0x2c78, "e"], + [0xff45, "e"], + [0x24a0, "(e)"], + [0x191, "F"], + [0x1e1e, "F"], + [0x24bb, "F"], + [0xa730, "F"], + [0xa77b, "F"], + [0xa7fb, "F"], + [0xff26, "F"], + [0x192, "f"], + [0x1d6e, "f"], + [0x1d82, "f"], + [0x1e1f, "f"], + [0x1e9b, "f"], + [0x24d5, "f"], + [0xa77c, "f"], + [0xff46, "f"], + [0x24a1, "(f)"], + [0xfb00, "ff"], + [0xfb03, "ffi"], + [0xfb04, "ffl"], + [0xfb01, "fi"], + [0xfb02, "fl"], + [0x11c, "G"], + [0x11e, "G"], + [0x120, "G"], + [0x122, "G"], + [0x193, "G"], + [0x1e4, "G"], + [0x1e5, "G"], + [0x1e6, "G"], + [0x1e7, "G"], + [0x1f4, "G"], + [0x262, "G"], + [0x29b, "G"], + [0x1e20, "G"], + [0x24bc, "G"], + [0xa77d, "G"], + [0xa77e, "G"], + [0xff27, "G"], + [0x11d, "g"], + [0x11f, "g"], + [0x121, "g"], + [0x123, "g"], + [0x1f5, "g"], + [0x260, "g"], + [0x261, "g"], + [0x1d77, "g"], + [0x1d79, "g"], + [0x1d83, "g"], + [0x1e21, "g"], + [0x24d6, "g"], + [0xa77f, "g"], + [0xff47, "g"], + [0x24a2, "(g)"], + [0x124, "H"], + [0x126, "H"], + [0x21e, "H"], + [0x29c, "H"], + [0x1e22, "H"], + [0x1e24, "H"], + [0x1e26, "H"], + [0x1e28, "H"], + [0x1e2a, "H"], + [0x24bd, "H"], + [0x2c67, "H"], + [0x2c75, "H"], + [0xff28, "H"], + [0x125, "h"], + [0x127, "h"], + [0x21f, "h"], + [0x265, "h"], + [0x266, "h"], + [0x2ae, "h"], + [0x2af, "h"], + [0x1e23, "h"], + [0x1e25, "h"], + [0x1e27, "h"], + [0x1e29, "h"], + [0x1e2b, "h"], + [0x1e96, "h"], + [0x24d7, "h"], + [0x2c68, "h"], + [0x2c76, "h"], + [0xff48, "h"], + [0x1f6, "HV"], + [0x24a3, "(h)"], + [0x195, "hv"], + [0xcc, "I"], + [0xcd, "I"], + [0xce, "I"], + [0xcf, "I"], + [0x128, "I"], + [0x12a, "I"], + [0x12c, "I"], + [0x12e, "I"], + [0x130, "I"], + [0x196, "I"], + [0x197, "I"], + [0x1cf, "I"], + [0x208, "I"], + [0x20a, "I"], + [0x26a, "I"], + [0x1d7b, "I"], + [0x1e2c, "I"], + [0x1e2e, "I"], + [0x1ec8, "I"], + [0x1eca, "I"], + [0x24be, "I"], + [0xa7fe, "I"], + [0xff29, "I"], + [0xec, "i"], + [0xed, "i"], + [0xee, "i"], + [0xef, "i"], + [0x129, "i"], + [0x12b, "i"], + [0x12d, "i"], + [0x12f, "i"], + [0x131, "i"], + [0x1d0, "i"], + [0x209, "i"], + [0x20b, "i"], + [0x268, "i"], + [0x1d09, "i"], + [0x1d62, "i"], + [0x1d7c, "i"], + [0x1d96, "i"], + [0x1e2d, "i"], + [0x1e2f, "i"], + [0x1ec9, "i"], + [0x1ecb, "i"], + [0x2071, "i"], + [0x24d8, "i"], + [0xff49, "i"], + [0x132, "IJ"], + [0x24a4, "(i)"], + [0x133, "ij"], + [0x134, "J"], + [0x248, "J"], + [0x1d0a, "J"], + [0x24bf, "J"], + [0xff2a, "J"], + [0x135, "j"], + [0x1f0, "j"], + [0x237, "j"], + [0x249, "j"], + [0x25f, "j"], + [0x284, "j"], + [0x29d, "j"], + [0x24d9, "j"], + [0x2c7c, "j"], + [0xff4a, "j"], + [0x24a5, "(j)"], + [0x136, "K"], + [0x198, "K"], + [0x1e8, "K"], + [0x1d0b, "K"], + [0x1e30, "K"], + [0x1e32, "K"], + [0x1e34, "K"], + [0x24c0, "K"], + [0x2c69, "K"], + [0xa740, "K"], + [0xa742, "K"], + [0xa744, "K"], + [0xff2b, "K"], + [0x137, "k"], + [0x199, "k"], + [0x1e9, "k"], + [0x29e, "k"], + [0x1d84, "k"], + [0x1e31, "k"], + [0x1e33, "k"], + [0x1e35, "k"], + [0x24da, "k"], + [0x2c6a, "k"], + [0xa741, "k"], + [0xa743, "k"], + [0xa745, "k"], + [0xff4b, "k"], + [0x24a6, "(k)"], + [0x139, "L"], + [0x13b, "L"], + [0x13d, "L"], + [0x13f, "L"], + [0x141, "L"], + [0x23d, "L"], + [0x29f, "L"], + [0x1d0c, "L"], + [0x1e36, "L"], + [0x1e38, "L"], + [0x1e3a, "L"], + [0x1e3c, "L"], + [0x24c1, "L"], + [0x2c60, "L"], + [0x2c62, "L"], + [0xa746, "L"], + [0xa748, "L"], + [0xa780, "L"], + [0xff2c, "L"], + [0x13a, "l"], + [0x13c, "l"], + [0x13e, "l"], + [0x140, "l"], + [0x142, "l"], + [0x19a, "l"], + [0x234, "l"], + [0x26b, "l"], + [0x26c, "l"], + [0x26d, "l"], + [0x1d85, "l"], + [0x1e37, "l"], + [0x1e39, "l"], + [0x1e3b, "l"], + [0x1e3d, "l"], + [0x24db, "l"], + [0x2c61, "l"], + [0xa747, "l"], + [0xa749, "l"], + [0xa781, "l"], + [0xff4c, "l"], + [0x1c7, "LJ"], + [0x1efa, "LL"], + [0x1c8, "Lj"], + [0x24a7, "(l)"], + [0x1c9, "lj"], + [0x1efb, "ll"], + [0x2aa, "ls"], + [0x2ab, "lz"], + [0x19c, "M"], + [0x1d0d, "M"], + [0x1e3e, "M"], + [0x1e40, "M"], + [0x1e42, "M"], + [0x24c2, "M"], + [0x2c6e, "M"], + [0xa7fd, "M"], + [0xa7ff, "M"], + [0xff2d, "M"], + [0x26f, "m"], + [0x270, "m"], + [0x271, "m"], + [0x1d6f, "m"], + [0x1d86, "m"], + [0x1e3f, "m"], + [0x1e41, "m"], + [0x1e43, "m"], + [0x24dc, "m"], + [0xff4d, "m"], + [0x24a8, "(m)"], + [0xd1, "N"], + [0x143, "N"], + [0x145, "N"], + [0x147, "N"], + [0x14a, "N"], + [0x19d, "N"], + [0x1f8, "N"], + [0x220, "N"], + [0x274, "N"], + [0x1d0e, "N"], + [0x1e44, "N"], + [0x1e46, "N"], + [0x1e48, "N"], + [0x1e4a, "N"], + [0x24c3, "N"], + [0xff2e, "N"], + [0xf1, "n"], + [0x144, "n"], + [0x146, "n"], + [0x148, "n"], + [0x149, "n"], + [0x14b, "n"], + [0x19e, "n"], + [0x1f9, "n"], + [0x235, "n"], + [0x272, "n"], + [0x273, "n"], + [0x1d70, "n"], + [0x1d87, "n"], + [0x1e45, "n"], + [0x1e47, "n"], + [0x1e49, "n"], + [0x1e4b, "n"], + [0x207f, "n"], + [0x24dd, "n"], + [0xff4e, "n"], + [0x1ca, "NJ"], + [0x1cb, "Nj"], + [0x24a9, "(n)"], + [0x1cc, "nj"], + [0xd2, "O"], + [0xd3, "O"], + [0xd4, "O"], + [0xd5, "O"], + [0xd6, "O"], + [0xd8, "O"], + [0x14c, "O"], + [0x14e, "O"], + [0x150, "O"], + [0x186, "O"], + [0x19f, "O"], + [0x1a0, "O"], + [0x1d1, "O"], + [0x1ea, "O"], + [0x1ec, "O"], + [0x1fe, "O"], + [0x20c, "O"], + [0x20e, "O"], + [0x22a, "O"], + [0x22c, "O"], + [0x22e, "O"], + [0x230, "O"], + [0x1d0f, "O"], + [0x1d10, "O"], + [0x1e4c, "O"], + [0x1e4e, "O"], + [0x1e50, "O"], + [0x1e52, "O"], + [0x1ecc, "O"], + [0x1ece, "O"], + [0x1ed0, "O"], + [0x1ed2, "O"], + [0x1ed4, "O"], + [0x1ed6, "O"], + [0x1ed8, "O"], + [0x1eda, "O"], + [0x1edc, "O"], + [0x1ede, "O"], + [0x1ee0, "O"], + [0x1ee2, "O"], + [0x24c4, "O"], + [0xa74a, "O"], + [0xa74c, "O"], + [0xff2f, "O"], + [0xf2, "o"], + [0xf3, "o"], + [0xf4, "o"], + [0xf5, "o"], + [0xf6, "o"], + [0xf8, "o"], + [0x14d, "o"], + [0x14f, "o"], + [0x151, "o"], + [0x1a1, "o"], + [0x1d2, "o"], + [0x1eb, "o"], + [0x1ed, "o"], + [0x1ff, "o"], + [0x20d, "o"], + [0x20f, "o"], + [0x22b, "o"], + [0x22d, "o"], + [0x22f, "o"], + [0x231, "o"], + [0x254, "o"], + [0x275, "o"], + [0x1d16, "o"], + [0x1d17, "o"], + [0x1d97, "o"], + [0x1e4d, "o"], + [0x1e4f, "o"], + [0x1e51, "o"], + [0x1e53, "o"], + [0x1ecd, "o"], + [0x1ecf, "o"], + [0x1ed1, "o"], + [0x1ed3, "o"], + [0x1ed5, "o"], + [0x1ed7, "o"], + [0x1ed9, "o"], + [0x1edb, "o"], + [0x1edd, "o"], + [0x1edf, "o"], + [0x1ee1, "o"], + [0x1ee3, "o"], + [0x2092, "o"], + [0x24de, "o"], + [0x2c7a, "o"], + [0xa74b, "o"], + [0xa74d, "o"], + [0xff4f, "o"], + [0x152, "OE"], + [0x276, "OE"], + [0xa74e, "OO"], + [0x222, "OU"], + [0x1d15, "OU"], + [0x24aa, "(o)"], + [0x153, "oe"], + [0x1d14, "oe"], + [0xa74f, "oo"], + [0x223, "ou"], + [0x1a4, "P"], + [0x1d18, "P"], + [0x1e54, "P"], + [0x1e56, "P"], + [0x24c5, "P"], + [0x2c63, "P"], + [0xa750, "P"], + [0xa752, "P"], + [0xa754, "P"], + [0xff30, "P"], + [0x1a5, "p"], + [0x1d71, "p"], + [0x1d7d, "p"], + [0x1d88, "p"], + [0x1e55, "p"], + [0x1e57, "p"], + [0x24df, "p"], + [0xa751, "p"], + [0xa753, "p"], + [0xa755, "p"], + [0xa7fc, "p"], + [0xff50, "p"], + [0x24ab, "(p)"], + [0x24a, "Q"], + [0x24c6, "Q"], + [0xa756, "Q"], + [0xa758, "Q"], + [0xff31, "Q"], + [0x138, "q"], + [0x24b, "q"], + [0x2a0, "q"], + [0x24e0, "q"], + [0xa757, "q"], + [0xa759, "q"], + [0xff51, "q"], + [0x24ac, "(q)"], + [0x239, "qp"], + [0x154, "R"], + [0x156, "R"], + [0x158, "R"], + [0x210, "R"], + [0x212, "R"], + [0x24c, "R"], + [0x280, "R"], + [0x281, "R"], + [0x1d19, "R"], + [0x1d1a, "R"], + [0x1e58, "R"], + [0x1e5a, "R"], + [0x1e5c, "R"], + [0x1e5e, "R"], + [0x24c7, "R"], + [0x2c64, "R"], + [0xa75a, "R"], + [0xa782, "R"], + [0xff32, "R"], + [0x155, "r"], + [0x157, "r"], + [0x159, "r"], + [0x211, "r"], + [0x213, "r"], + [0x24d, "r"], + [0x27c, "r"], + [0x27d, "r"], + [0x27e, "r"], + [0x27f, "r"], + [0x1d63, "r"], + [0x1d72, "r"], + [0x1d73, "r"], + [0x1d89, "r"], + [0x1e59, "r"], + [0x1e5b, "r"], + [0x1e5d, "r"], + [0x1e5f, "r"], + [0x24e1, "r"], + [0xa75b, "r"], + [0xa783, "r"], + [0xff52, "r"], + [0x24ad, "(r)"], + [0x15a, "S"], + [0x15c, "S"], + [0x15e, "S"], + [0x160, "S"], + [0x218, "S"], + [0x1e60, "S"], + [0x1e62, "S"], + [0x1e64, "S"], + [0x1e66, "S"], + [0x1e68, "S"], + [0x24c8, "S"], + [0xa731, "S"], + [0xa785, "S"], + [0xff33, "S"], + [0x15b, "s"], + [0x15d, "s"], + [0x15f, "s"], + [0x161, "s"], + [0x17f, "s"], + [0x219, "s"], + [0x23f, "s"], + [0x282, "s"], + [0x1d74, "s"], + [0x1d8a, "s"], + [0x1e61, "s"], + [0x1e63, "s"], + [0x1e65, "s"], + [0x1e67, "s"], + [0x1e69, "s"], + [0x1e9c, "s"], + [0x1e9d, "s"], + [0x24e2, "s"], + [0xa784, "s"], + [0xff53, "s"], + [0x1e9e, "SS"], + [0x24ae, "(s)"], + [0xdf, "ss"], + [0xfb06, "st"], + [0x162, "T"], + [0x164, "T"], + [0x166, "T"], + [0x1ac, "T"], + [0x1ae, "T"], + [0x21a, "T"], + [0x23e, "T"], + [0x1d1b, "T"], + [0x1e6a, "T"], + [0x1e6c, "T"], + [0x1e6e, "T"], + [0x1e70, "T"], + [0x24c9, "T"], + [0xa786, "T"], + [0xff34, "T"], + [0x163, "t"], + [0x165, "t"], + [0x167, "t"], + [0x1ab, "t"], + [0x1ad, "t"], + [0x21b, "t"], + [0x236, "t"], + [0x287, "t"], + [0x288, "t"], + [0x1d75, "t"], + [0x1e6b, "t"], + [0x1e6d, "t"], + [0x1e6f, "t"], + [0x1e71, "t"], + [0x1e97, "t"], + [0x24e3, "t"], + [0x2c66, "t"], + [0xff54, "t"], + [0xde, "TH"], + [0xa766, "TH"], + [0xa728, "TZ"], + [0x24af, "(t)"], + [0x2a8, "tc"], + [0xfe, "th"], + [0x1d7a, "th"], + [0xa767, "th"], + [0x2a6, "ts"], + [0xa729, "tz"], + [0xd9, "U"], + [0xda, "U"], + [0xdb, "U"], + [0xdc, "U"], + [0x168, "U"], + [0x16a, "U"], + [0x16c, "U"], + [0x16e, "U"], + [0x170, "U"], + [0x172, "U"], + [0x1af, "U"], + [0x1d3, "U"], + [0x1d5, "U"], + [0x1d7, "U"], + [0x1d9, "U"], + [0x1db, "U"], + [0x214, "U"], + [0x216, "U"], + [0x244, "U"], + [0x1d1c, "U"], + [0x1d7e, "U"], + [0x1e72, "U"], + [0x1e74, "U"], + [0x1e76, "U"], + [0x1e78, "U"], + [0x1e7a, "U"], + [0x1ee4, "U"], + [0x1ee6, "U"], + [0x1ee8, "U"], + [0x1eea, "U"], + [0x1eec, "U"], + [0x1eee, "U"], + [0x1ef0, "U"], + [0x24ca, "U"], + [0xff35, "U"], + [0xf9, "u"], + [0xfa, "u"], + [0xfb, "u"], + [0xfc, "u"], + [0x169, "u"], + [0x16b, "u"], + [0x16d, "u"], + [0x16f, "u"], + [0x171, "u"], + [0x173, "u"], + [0x1b0, "u"], + [0x1d4, "u"], + [0x1d6, "u"], + [0x1d8, "u"], + [0x1da, "u"], + [0x1dc, "u"], + [0x215, "u"], + [0x217, "u"], + [0x289, "u"], + [0x1d64, "u"], + [0x1d99, "u"], + [0x1e73, "u"], + [0x1e75, "u"], + [0x1e77, "u"], + [0x1e79, "u"], + [0x1e7b, "u"], + [0x1ee5, "u"], + [0x1ee7, "u"], + [0x1ee9, "u"], + [0x1eeb, "u"], + [0x1eed, "u"], + [0x1eef, "u"], + [0x1ef1, "u"], + [0x24e4, "u"], + [0xff55, "u"], + [0x24b0, "(u)"], + [0x1d6b, "ue"], + [0x1b2, "V"], + [0x245, "V"], + [0x1d20, "V"], + [0x1e7c, "V"], + [0x1e7e, "V"], + [0x1efc, "V"], + [0x24cb, "V"], + [0xa75e, "V"], + [0xa768, "V"], + [0xff36, "V"], + [0x28b, "v"], + [0x28c, "v"], + [0x1d65, "v"], + [0x1d8c, "v"], + [0x1e7d, "v"], + [0x1e7f, "v"], + [0x24e5, "v"], + [0x2c71, "v"], + [0x2c74, "v"], + [0xa75f, "v"], + [0xff56, "v"], + [0xa760, "VY"], + [0x24b1, "(v)"], + [0xa761, "vy"], + [0x174, "W"], + [0x1f7, "W"], + [0x1d21, "W"], + [0x1e80, "W"], + [0x1e82, "W"], + [0x1e84, "W"], + [0x1e86, "W"], + [0x1e88, "W"], + [0x24cc, "W"], + [0x2c72, "W"], + [0xff37, "W"], + [0x175, "w"], + [0x1bf, "w"], + [0x28d, "w"], + [0x1e81, "w"], + [0x1e83, "w"], + [0x1e85, "w"], + [0x1e87, "w"], + [0x1e89, "w"], + [0x1e98, "w"], + [0x24e6, "w"], + [0x2c73, "w"], + [0xff57, "w"], + [0x24b2, "(w)"], + [0x1e8a, "X"], + [0x1e8c, "X"], + [0x24cd, "X"], + [0xff38, "X"], + [0x1d8d, "x"], + [0x1e8b, "x"], + [0x1e8d, "x"], + [0x2093, "x"], + [0x24e7, "x"], + [0xff58, "x"], + [0x24b3, "(x)"], + [0xdd, "Y"], + [0x176, "Y"], + [0x178, "Y"], + [0x1b3, "Y"], + [0x232, "Y"], + [0x24e, "Y"], + [0x28f, "Y"], + [0x1e8e, "Y"], + [0x1ef2, "Y"], + [0x1ef4, "Y"], + [0x1ef6, "Y"], + [0x1ef8, "Y"], + [0x1efe, "Y"], + [0x24ce, "Y"], + [0xff39, "Y"], + [0xfd, "y"], + [0xff, "y"], + [0x177, "y"], + [0x1b4, "y"], + [0x233, "y"], + [0x24f, "y"], + [0x28e, "y"], + [0x1e8f, "y"], + [0x1e99, "y"], + [0x1ef3, "y"], + [0x1ef5, "y"], + [0x1ef7, "y"], + [0x1ef9, "y"], + [0x1eff, "y"], + [0x24e8, "y"], + [0xff59, "y"], + [0x24b4, "(y)"], + [0x179, "Z"], + [0x17b, "Z"], + [0x17d, "Z"], + [0x1b5, "Z"], + [0x21c, "Z"], + [0x224, "Z"], + [0x1d22, "Z"], + [0x1e90, "Z"], + [0x1e92, "Z"], + [0x1e94, "Z"], + [0x24cf, "Z"], + [0x2c6b, "Z"], + [0xa762, "Z"], + [0xff3a, "Z"], + [0x17a, "z"], + [0x17c, "z"], + [0x17e, "z"], + [0x1b6, "z"], + [0x21d, "z"], + [0x225, "z"], + [0x240, "z"], + [0x290, "z"], + [0x291, "z"], + [0x1d76, "z"], + [0x1d8e, "z"], + [0x1e91, "z"], + [0x1e93, "z"], + [0x1e95, "z"], + [0x24e9, "z"], + [0x2c6c, "z"], + [0xa763, "z"], + [0xff5a, "z"], + [0x24b5, "(z)"], + [0x2070, "0"], + [0x2080, "0"], + [0x24ea, "0"], + [0x24ff, "0"], + [0xff10, "0"], + [0xb9, "1"], + [0x2081, "1"], + [0x2460, "1"], + [0x24f5, "1"], + [0x2776, "1"], + [0x2780, "1"], + [0x278a, "1"], + [0xff11, "1"], + [0x2488, "1."], + [0x2474, "(1)"], + [0xb2, "2"], + [0x2082, "2"], + [0x2461, "2"], + [0x24f6, "2"], + [0x2777, "2"], + [0x2781, "2"], + [0x278b, "2"], + [0xff12, "2"], + [0x2489, "2."], + [0x2475, "(2)"], + [0xb3, "3"], + [0x2083, "3"], + [0x2462, "3"], + [0x24f7, "3"], + [0x2778, "3"], + [0x2782, "3"], + [0x278c, "3"], + [0xff13, "3"], + [0x248a, "3."], + [0x2476, "(3)"], + [0x2074, "4"], + [0x2084, "4"], + [0x2463, "4"], + [0x24f8, "4"], + [0x2779, "4"], + [0x2783, "4"], + [0x278d, "4"], + [0xff14, "4"], + [0x248b, "4."], + [0x2477, "(4)"], + [0x2075, "5"], + [0x2085, "5"], + [0x2464, "5"], + [0x24f9, "5"], + [0x277a, "5"], + [0x2784, "5"], + [0x278e, "5"], + [0xff15, "5"], + [0x248c, "5."], + [0x2478, "(5)"], + [0x2076, "6"], + [0x2086, "6"], + [0x2465, "6"], + [0x24fa, "6"], + [0x277b, "6"], + [0x2785, "6"], + [0x278f, "6"], + [0xff16, "6"], + [0x248d, "6."], + [0x2479, "(6)"], + [0x2077, "7"], + [0x2087, "7"], + [0x2466, "7"], + [0x24fb, "7"], + [0x277c, "7"], + [0x2786, "7"], + [0x2790, "7"], + [0xff17, "7"], + [0x248e, "7."], + [0x247a, "(7)"], + [0x2078, "8"], + [0x2088, "8"], + [0x2467, "8"], + [0x24fc, "8"], + [0x277d, "8"], + [0x2787, "8"], + [0x2791, "8"], + [0xff18, "8"], + [0x248f, "8."], + [0x247b, "(8)"], + [0x2079, "9"], + [0x2089, "9"], + [0x2468, "9"], + [0x24fd, "9"], + [0x277e, "9"], + [0x2788, "9"], + [0x2792, "9"], + [0xff19, "9"], + [0x2490, "9."], + [0x247c, "(9)"], + [0x2469, "10"], + [0x24fe, "10"], + [0x277f, "10"], + [0x2789, "10"], + [0x2793, "10"], + [0x2491, "10."], + [0x247d, "(10)"], + [0x246a, "11"], + [0x24eb, "11"], + [0x2492, "11."], + [0x247e, "(11)"], + [0x246b, "12"], + [0x24ec, "12"], + [0x2493, "12."], + [0x247f, "(12)"], + [0x246c, "13"], + [0x24ed, "13"], + [0x2494, "13."], + [0x2480, "(13)"], + [0x246d, "14"], + [0x24ee, "14"], + [0x2495, "14."], + [0x2481, "(14)"], + [0x246e, "15"], + [0x24ef, "15"], + [0x2496, "15."], + [0x2482, "(15)"], + [0x246f, "16"], + [0x24f0, "16"], + [0x2497, "16."], + [0x2483, "(16)"], + [0x2470, "17"], + [0x24f1, "17"], + [0x2498, "17."], + [0x2484, "(17)"], + [0x2471, "18"], + [0x24f2, "18"], + [0x2499, "18."], + [0x2485, "(18)"], + [0x2472, "19"], + [0x24f3, "19"], + [0x249a, "19."], + [0x2486, "(19)"], + [0x2473, "20"], + [0x24f4, "20"], + [0x249b, "20."], + [0x2487, "(20)"], + [0xab, '"'], + [0xbb, '"'], + [0x201c, '"'], + [0x201d, '"'], + [0x201e, '"'], + [0x2033, '"'], + [0x2036, '"'], + [0x275d, '"'], + [0x275e, '"'], + [0x276e, '"'], + [0x276f, '"'], + [0xff02, '"'], + [0x2018, "'"], + [0x2019, "'"], + [0x201a, "'"], + [0x201b, "'"], + [0x2032, "'"], + [0x2035, "'"], + [0x2039, "'"], + [0x203a, "'"], + [0x275b, "'"], + [0x275c, "'"], + [0xff07, "'"], + [0x2010, "-"], + [0x2011, "-"], + [0x2012, "-"], + [0x2013, "-"], + [0x2014, "-"], + [0x207b, "-"], + [0x208b, "-"], + [0xff0d, "-"], + [0x2045, "["], + [0x2772, "["], + [0xff3b, "["], + [0x2046, "]"], + [0x2773, "]"], + [0xff3d, "]"], + [0x207d, "("], + [0x208d, "("], + [0x2768, "("], + [0x276a, "("], + [0xff08, "("], + [0x2e28, "(("], + [0x207e, ")"], + [0x208e, ")"], + [0x2769, ")"], + [0x276b, ")"], + [0xff09, ")"], + [0x2e29, "))"], + [0x276c, "<"], + [0x2770, "<"], + [0xff1c, "<"], + [0x276d, ">"], + [0x2771, ">"], + [0xff1e, ">"], + [0x2774, "{"], + [0xff5b, "{"], + [0x2775, "}"], + [0xff5d, "}"], + [0x207a, "+"], + [0x208a, "+"], + [0xff0b, "+"], + [0x207c, "="], + [0x208c, "="], + [0xff1d, "="], + [0xff01, "!"], + [0x203c, "!!"], + [0x2049, "!?"], + [0xff03, "#"], + [0xff04, "$"], + [0x2052, "%"], + [0xff05, "%"], + [0xff06, "&"], + [0x204e, "*"], + [0xff0a, "*"], + [0xff0c, ","], + [0xff0e, "."], + [0x2044, "/"], + [0xff0f, "/"], + [0xff1a, ":"], + [0x204f, ";"], + [0xff1b, ";"], + [0xff1f, "?"], + [0x2047, "??"], + [0x2048, "?!"], + [0xff20, "@"], + [0xff3c, "\\"], + [0x2038, "^"], + [0xff3e, "^"], + [0xff3f, "_"], + [0x2053, "~"], + [0xff5e, "~"], +]); + +export default ASCIIFolder; diff --git a/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/index.ts b/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/index.ts index c11378b3d2..5cc6386e53 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/index.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/index.ts @@ -16,19 +16,19 @@ import { SearchAdapter } from "../abstract"; import { DatabaseServiceAPI } from "../../../database/api"; import { getEntityDefinition, unwrapPrimarykey } from "../../api"; import { ListResult, Paginable, Pagination } from "../../../../framework/api/crud-service"; -import { parsePrimaryKey, stringifyPrimaryKey } from "../utils"; +import { asciiFold, parsePrimaryKey, stringifyPrimaryKey } from "../utils"; import { ApiResponse } from "@elastic/elasticsearch/lib/Transport"; import { buildSearchQuery } from "./search"; type Operation = { - index?: { _index: string; _id: string; _type: string }; - delete?: { _index: string; _id: string; _type: string }; + index?: { _index: string; _id: string }; + delete?: { _index: string; _id: string }; [key: string]: any; }; export default class ElasticSearch extends SearchAdapter implements SearchAdapterInterface { private client: Client; - private bulkReaders: number = 0; + private bulkReaders = 0; private buffer: Operation[] = []; private name = "ElasticSearch"; @@ -61,9 +61,6 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte const name = entity.options?.search?.index || entity.name; const mapping = entity.options?.search?.esMapping; - let mappings: any = {}; - mappings[`_doc`] = { ...mapping, _source: { enabled: true } }; - try { await this.client.indices.get({ index: name, @@ -72,25 +69,24 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte } catch (e) { logger.info(`Create index ${name} with mapping %o`, mapping); - const rep = await this.client.indices.create( - { - index: name, - body: { - settings: { - analysis: { - analyzer: { - folding: { - tokenizer: "standard", - filter: ["lowercase", "asciifolding"], - }, + const indice = { + index: name, + body: { + settings: { + analysis: { + analyzer: { + folding: { + tokenizer: "standard", + filter: ["lowercase", "asciifolding"], }, }, }, - mappings: { ...mappings }, }, + mappings: { ...mapping, _source: { enabled: false } }, }, - { ignore: [400] }, - ); + }; + + const rep = await this.client.indices.create(indice, { ignore: [400] }); if (rep.statusCode !== 200) { logger.error(`${this.name} - ${JSON.stringify(rep.body)}`); @@ -126,13 +122,21 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte ...entityDefinition.options.search.source(entity), }; + Object.keys(entityDefinition.options?.search.esMapping?.properties || []).forEach( + (key: string) => { + const mapping: any = entityDefinition.options?.search?.esMapping?.properties[key]; + if (mapping.type === "text") { + body[key] = asciiFold(body[key]).toLocaleLowerCase(); + } + }, + ); + const index = entityDefinition.options?.search?.index || entityDefinition.name; const record: Operation = { index: { _index: index, _id: stringifyPrimaryKey(entity), - _type: `_doc`, }, ...body, }; @@ -161,7 +165,6 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte delete: { _index: index, _id: stringifyPrimaryKey(entity), - _type: `_doc`, }, }; @@ -178,7 +181,7 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte return; } - logger.info(`Start new Elasticsearch bulk reader.`); + logger.info("Start new Elasticsearch bulk reader."); this.bulkReaders += 1; let buffer; @@ -221,9 +224,13 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte onDrop: res => { const doc = res.document; logger.error( - `Operation ${doc.action} was droped while pushing to elasticsearch index ${doc.index} (doc.id: ${doc.id})`, - res.error, + `Operation ${ + doc.action + } was droped while pushing to elasticsearch index ${JSON.stringify( + doc.index, + )} (doc.id: ${doc.id})`, ); + logger.error(res.error); }, }); } catch (err) { @@ -231,7 +238,7 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte logger.error(err); } - logger.info(`Elasticsearch bulk flushed.`); + logger.info("Elasticsearch bulk flushed."); this.bulkReaders += -1; this.startBulkReader(); @@ -254,9 +261,12 @@ export default class ElasticSearch extends SearchAdapter implements SearchAdapte }; let esResponse: ApiResponse; + if (options.pagination.page_token) { esResponse = await this.client.scroll( - { scroll_id: options.pagination.page_token, ...esParamsWithScroll }, + { + scroll_id: options.pagination.page_token, + }, esOptions, ); } else { diff --git a/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/search.ts b/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/search.ts index c6cd68a5fb..5e8b1a52e7 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/search.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/elasticsearch/search.ts @@ -3,6 +3,7 @@ import { TransportRequestOptions } from "@elastic/elasticsearch/lib/Transport"; import _ from "lodash"; import { logger } from "../../../../../../core/platform/framework/logger"; import { EntityTarget, FindFilter, FindOptions, getEntityDefinition } from "../../api"; +import { asciiFold } from "../utils"; export function buildSearchQuery( entityType: EntityTarget, @@ -13,7 +14,7 @@ export function buildSearchQuery( const { entityDefinition, columnsDefinition } = getEntityDefinition(instance); const indexProperties = entityDefinition.options.search.esMapping.properties || {}; - let esBody: any = { + const esBody: any = { query: { bool: { boost: 1.0, @@ -24,7 +25,7 @@ export function buildSearchQuery( if (Object.keys(filters || {}).length > 0) { esBody.query.bool.must = esBody.query.bool.must || []; for (const [key, value] of Object.entries(filters)) { - let match: any = {}; + const match: any = {}; match[key] = { query: value, operator: "AND" }; esBody.query.bool.must.push({ match }); } @@ -34,9 +35,9 @@ export function buildSearchQuery( esBody.query.bool.must = esBody.query.bool.must || []; for (const inOperation of options.$in) { if (inOperation[1].length > 0) { - let bool: any = { bool: { should: [], minimum_should_match: 1 } }; + const bool: any = { bool: { should: [], minimum_should_match: 1 } }; for (const value of inOperation[1]) { - let match: any = {}; + const match: any = {}; match[inOperation[0]] = { query: value, operator: "AND" }; bool.bool.should.push({ match }); } @@ -51,19 +52,36 @@ export function buildSearchQuery( esBody.query.bool.minimum_should_match = 1; esBody.query.bool.should = esBody.query.bool.should || []; + if (options?.$text?.$search) + options.$text.$search = asciiFold(options.$text.$search || "").toLocaleLowerCase(); + for (const [key, value] of Object.entries(indexProperties)) { if ((value as any)["type"] === "text") { - let match: any = {}; + const match: any = {}; match[key] = { - query: options.$text.$search, + query: (options.$text.$search || "").toLocaleLowerCase(), }; esBody.query.bool.should.push({ match, }); + + //Allow prefix search + if (indexProperties[key].index_prefixes !== undefined) { + esBody.query.bool.should.push({ + prefix: { [key]: { value: (options.$text.$search || "").toLocaleLowerCase() } }, + }); + } } } } + if (options.$sort) { + for (const [key, value] of Object.entries(options.$sort)) { + esBody.sort = esBody.sort || []; + esBody.sort.push({ [key]: value }); + } + } + //TODO implement regex search logger.debug(`Elasticsearch query: ${JSON.stringify(esBody)}`); @@ -73,7 +91,7 @@ export function buildSearchQuery( body: esBody, }; - let esOptions: TransportRequestOptions = { + const esOptions: TransportRequestOptions = { ignore: [404], maxRetries: 3, }; diff --git a/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts b/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts index e8228f99c1..302cb0d546 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/index.ts @@ -16,7 +16,7 @@ import { import { SearchAdapter } from "../abstract"; import { ListResult, Paginable, Pagination } from "../../../../framework/api/crud-service"; import { MongoConnector } from "../../../database/services/orm/connectors"; -import { parsePrimaryKey, stringifyPrimaryKey } from "../utils"; +import { asciiFold, parsePrimaryKey, stringifyPrimaryKey } from "../utils"; import { buildSearchQuery } from "./search"; const searchPrefix = "search__"; @@ -53,6 +53,8 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI return; } + logger.info(`${this.name} - Start compute index ${JSON.stringify(entityDefinition)}`); + const index = this.getIndex(entityDefinition); const collection = this.mongodb.collection(`${searchPrefix}${index}`); @@ -62,7 +64,7 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI indexedPk[key] = 1; }); - const indexedFields: any = entityDefinition.options.search.mongoMapping || {}; + let indexedFields: any = entityDefinition.options.search.mongoMapping || {}; if (!entityDefinition.options.search.mongoMapping) { Object.keys(columns).forEach(c => { const def = columns[c]; @@ -72,9 +74,17 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI }); } + indexedFields = _.pick(indexedFields, ["text"]); + + logger.info( + `${this.name} - Create indexes ${JSON.stringify(indexedFields)} for ${ + entityDefinition.name + } (${searchPrefix}${index})`, + ); + //Create one index for each type of indexes ["text"] Object.keys(indexedFields).forEach(k => { - collection.createIndex(indexedFields[k]); + collection.createIndex(indexedFields[k], { default_language: "none" }); }); } @@ -106,6 +116,14 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI ...entityDefinition.options.search.source(entity), }; + Object.keys(entityDefinition.options?.search.mongoMapping?.text || []).forEach( + (key: string) => { + if (entityDefinition.options?.search.mongoMapping?.text[key] === "text") { + body[key] = asciiFold(body[key]).toLocaleLowerCase(); + } + }, + ); + const record: Operation = { index: this.getIndex(entityDefinition), id: stringifyPrimaryKey(entity), @@ -147,6 +165,9 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI private async proceed(operation: Operation) { const collection = this.mongodb.collection(`${searchPrefix}${operation.index}`); + logger.info( + `Process all buffered operations on searchable entity ${searchPrefix}${operation.index}`, + ); if (operation.action === "remove") { await collection.deleteOne({ _docId: operation.id }); } @@ -166,13 +187,19 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI options: FindOptions = {}, ) { const instance = new (entityType as any)(); - const { entityDefinition } = getEntityDefinition(instance); + const { entityDefinition, columnsDefinition } = getEntityDefinition(instance); const index = this.getIndex(entityDefinition); + logger.info(`Run search on entity ${searchPrefix}${index}`); + + await this.ensureIndex(entityDefinition, columnsDefinition, this.createIndex.bind(this)); + const collection = this.mongodb.collection(`${searchPrefix}${index}`); const { query, sort, project } = buildSearchQuery(entityType, filters, options); + console.log(query); + let cursor = collection.find({ ...query }).sort(sort); if (project) { cursor = cursor.project(project); @@ -204,6 +231,8 @@ export default class MongoSearch extends SearchAdapter implements SearchAdapterI (parseInt(options.pagination.page_token) + 1).toString(10); const nextPage: Paginable = new Pagination(nextToken, options.pagination.limitStr || "100"); + logger.info(`Found ${entities.length} results on entity ${searchPrefix}${index}`); + return new ListResult(entityDefinition.type, entities, nextPage); } } diff --git a/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/search.ts b/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/search.ts index af36b44e30..ccf07c7477 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/search.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/mongosearch/search.ts @@ -1,12 +1,16 @@ import _ from "lodash"; import { buildSelectQuery } from "../../../database/services/orm/connectors/mongodb/query-builder"; import { EntityTarget, FindFilter, FindOptions, getEntityDefinition } from "../../api"; +import { asciiFold } from "../utils"; export function buildSearchQuery( entityType: EntityTarget, filters: FindFilter, options: FindOptions = {}, ): { project: any; query: any; sort: any } { + const instance = new (entityType as any)(); + const { entityDefinition } = getEntityDefinition(instance); + let project: any = false; let query: any = {}; try { @@ -18,9 +22,28 @@ export function buildSearchQuery( //Build text searches if (options.$text) { - project = { score: { $meta: "textScore" } }; - sort = { score: -1 }; - query.$text = options.$text || undefined; + const prefixMapping = entityDefinition?.options?.search?.mongoMapping?.prefix || {}; + const textMapping = entityDefinition?.options?.search?.mongoMapping?.text || {}; + //Try to detect when we need prefix search + if (Object.values(prefixMapping).length > 0 && options.$text.$search.indexOf(" ") < 0) { + query.$or = [...Object.keys(prefixMapping), ...Object.keys(textMapping)].map(k => { + if (prefixMapping[k] === "prefix") { + return { + [k]: new RegExp(`^${asciiFold(options.$text.$search || "")}`, "i"), + }; + } else { + return { + [k]: new RegExp(`${asciiFold(options.$text.$search || "")}`, "i"), + }; + } + }); + } else { + project = { score: { $meta: "textScore" } }; + sort = { score: -1 }; + if (options?.$text?.$search) + options.$text.$search = asciiFold(options.$text.$search || "").toLocaleLowerCase(); + query.$text = options.$text || undefined; + } } //Build regexes diff --git a/twake/backend/node/src/core/platform/services/search/adapters/utils.ts b/twake/backend/node/src/core/platform/services/search/adapters/utils.ts index dcf02ff218..507fb2f21f 100644 --- a/twake/backend/node/src/core/platform/services/search/adapters/utils.ts +++ b/twake/backend/node/src/core/platform/services/search/adapters/utils.ts @@ -1,5 +1,6 @@ import _ from "lodash"; import { getEntityDefinition, unwrapPrimarykey, EntityDefinition } from "../api"; +import ASCIIFolder from "./ascii-folder"; export function stringifyPrimaryKey(entity: any): string { const { entityDefinition } = getEntityDefinition(entity); @@ -13,17 +14,26 @@ export function parsePrimaryKey( ): { [key: string]: any } { const pkColumns = unwrapPrimarykey(entityDefinition).sort((a, b) => a.localeCompare(b)); const pkList = JSON.parse(pkStr); - let pk: { [key: string]: any } = {}; + const pk: { [key: string]: any } = {}; pkColumns.forEach((c, index) => { pk[c] = pkList[index]; }); return pk; } -export function expandStringForPrefix(str: string, minimalSize: number = 3) { - let expanded: string[] = []; +export function expandStringForPrefix( + str: string, + minimalSize: number = 1, + maximalSize: number = 5, +) { + const expanded: string[] = []; [...str.split(" "), ...str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, " ").split(" ")].map(w => { - for (let i = minimalSize; i <= w.length; i++) expanded.push(w.slice(0, i)); + for (let i = minimalSize; i <= Math.min(maximalSize, w.length); i++) + expanded.push(w.slice(0, i)); }); return _.uniq(expanded).join(" "); } + +export function asciiFold(str: string) { + return ASCIIFolder.foldMaintaining(str); +} diff --git a/twake/backend/node/src/core/platform/services/search/api.ts b/twake/backend/node/src/core/platform/services/search/api.ts index 7dd6e17662..87f03fde87 100644 --- a/twake/backend/node/src/core/platform/services/search/api.ts +++ b/twake/backend/node/src/core/platform/services/search/api.ts @@ -1,11 +1,13 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types */ import { TwakeServiceProvider } from "../../framework"; -import { ListResult, Pagination } from "../../framework/api/crud-service"; +import { ListResult } from "../../framework/api/crud-service"; import { FindFilter as OrmFindFilter, FindOptions as OrmFindOptions, } from "../database/services/orm/repository/repository"; import { EntityTarget } from "../database/services/orm/types"; import SearchRepository from "./repository"; + export { getEntityDefinition, unwrapPrimarykey } from "../database/services/orm/utils"; export { DatabaseEntitiesRemovedEvent, @@ -24,12 +26,17 @@ type TextType = { $diacriticSensitive?: boolean; //Default false }; +type SortType = { + [key: string]: "asc" | "desc"; +}; + //Field, regex, options type RegexType = [string, string, string]; export type FindOptions = OrmFindOptions & { $regex?: RegexType[]; $text?: TextType; + $sort?: SortType; }; export type IndexedEntity = { @@ -54,6 +61,7 @@ export interface SearchServiceAPI extends TwakeServiceProvider { getRepository(table: string, entityType: EntityTarget): SearchRepository; upsert(entities: any[]): Promise; remove(entities: any[]): Promise; + type: SearchConfiguration["type"]; } export type SearchConfiguration = { diff --git a/twake/backend/node/src/core/platform/services/search/index.ts b/twake/backend/node/src/core/platform/services/search/index.ts index 50e500c0d2..b7778bb797 100644 --- a/twake/backend/node/src/core/platform/services/search/index.ts +++ b/twake/backend/node/src/core/platform/services/search/index.ts @@ -9,7 +9,7 @@ import { } from "./api"; import ElasticsearchService from "./adapters/elasticsearch"; import MongosearchService from "./adapters/mongosearch"; -import { localEventBus } from "../../framework/pubsub"; +import { localEventBus } from "../../framework/event-bus"; import { DatabaseServiceAPI } from "../database/api"; import SearchRepository from "./repository"; @@ -20,9 +20,11 @@ export default class Search extends TwakeService { name = "search"; service: SearchAdapterInterface; database: DatabaseServiceAPI; + type: SearchConfiguration["type"]; public async doInit(): Promise { const type = this.configuration.get("type") as SearchConfiguration["type"]; + this.type = type; this.database = this.context.getProvider("database"); if (type === "elasticsearch") { diff --git a/twake/backend/node/src/core/platform/services/search/repository.ts b/twake/backend/node/src/core/platform/services/search/repository.ts index 5dbb282c47..359da83d07 100644 --- a/twake/backend/node/src/core/platform/services/search/repository.ts +++ b/twake/backend/node/src/core/platform/services/search/repository.ts @@ -1,6 +1,11 @@ import Search from "."; import { logger } from "../../framework"; -import { ListResult, Paginable, Pagination } from "../../framework/api/crud-service"; +import { + ExecutionContext, + ListResult, + Paginable, + Pagination, +} from "../../framework/api/crud-service"; import { EntityTarget, FindFilter, FindOptions, getEntityDefinition } from "./api"; export default class SearchRepository { @@ -13,7 +18,7 @@ export default class SearchRepository { ) {} /** Execute a search over defined search database (mongo or elastic search) */ - public async search(filters: FindFilter, options: FindOptions = {}) { + public async search(filters: FindFilter, options: FindOptions = {}, context?: ExecutionContext) { logger.debug( `${this.name} Run search for table ${this.table} with filter ${JSON.stringify( filters, @@ -24,7 +29,7 @@ export default class SearchRepository { const { entityDefinition } = getEntityDefinition(instance); const repository = await this.service.database.getRepository(this.table, this.entityType); - let results: EntityType[] = []; + const results: EntityType[] = []; let nextPage: Paginable = new Pagination(); try { //1. Get objects primary keys from search connector @@ -37,7 +42,7 @@ export default class SearchRepository { //2. Get database original objects from theses primary keys for (const searchEntity of searchResults.getEntities().sort((a, b) => b.score - a.score)) { - const sourceEntity = await repository.findOne(searchEntity.primaryKey); + const sourceEntity = await repository.findOne(searchEntity.primaryKey, {}, context); if (sourceEntity) { results.push(sourceEntity); } else { diff --git a/twake/backend/node/src/core/platform/services/storage/connectors/S3/service.ts b/twake/backend/node/src/core/platform/services/storage/connectors/S3/service.ts index 5d96e25dfe..a5bac23712 100644 --- a/twake/backend/node/src/core/platform/services/storage/connectors/S3/service.ts +++ b/twake/backend/node/src/core/platform/services/storage/connectors/S3/service.ts @@ -1,4 +1,5 @@ import * as Minio from "minio"; +import { logger } from "../../../../../../core/platform/framework"; import { Readable } from "stream"; import { StorageConnectorAPI, WriteMetadata } from "../../provider"; @@ -31,6 +32,27 @@ export default class S3ConnectorService implements StorageConnectorAPI { } async read(path: string): Promise { + // Test if file exists in S3 bucket 10 times until we find it + const tries = 10; + let err = null; + for (let i = 0; i <= tries; i++) { + try { + const stat = await this.client.statObject(this.minioConfiguration.bucket, path); + if (stat?.size > 0) { + break; + } + } catch (e) { + err = e; + } + + if (i === tries) { + logger.info(`Unable to get file after ${tries} tries:`); + throw err; + } + + await new Promise(r => setTimeout(r, 500)); + logger.info(`File ${path} not found in S3 bucket, retrying...`); + } return this.client.getObject(this.minioConfiguration.bucket, path); } diff --git a/twake/backend/node/src/core/platform/services/storage/index.ts b/twake/backend/node/src/core/platform/services/storage/index.ts index 15ab6b7631..ffc96e475b 100644 --- a/twake/backend/node/src/core/platform/services/storage/index.ts +++ b/twake/backend/node/src/core/platform/services/storage/index.ts @@ -82,12 +82,6 @@ export default class StorageService extends TwakeService implements // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; - let decipher: Decipher; - if (options?.encryptionKey) { - const [key, iv] = options.encryptionKey.split("."); - decipher = createDecipheriv(options.encryptionAlgo || this.algorithm, key, iv); - } - const chunks = options?.totalChunks || 1; let count = 1; let stream; @@ -97,6 +91,12 @@ export default class StorageService extends TwakeService implements return; } + let decipher: Decipher; + if (options?.encryptionKey) { + const [key, iv] = options.encryptionKey.split("."); + decipher = createDecipheriv(options.encryptionAlgo || this.algorithm, key, iv); + } + const chunk = options?.totalChunks ? `${path}/chunk${count}` : path; count += 1; diff --git a/twake/backend/node/src/core/platform/services/storage/provider.ts b/twake/backend/node/src/core/platform/services/storage/provider.ts index 76a4c9d571..f6149853ff 100644 --- a/twake/backend/node/src/core/platform/services/storage/provider.ts +++ b/twake/backend/node/src/core/platform/services/storage/provider.ts @@ -1,5 +1,6 @@ import { Stream, Readable } from "stream"; import { TwakeServiceProvider } from "../../framework"; +import { ExecutionContext } from "../../framework/api/crud-service"; export type WriteMetadata = { size: number; @@ -28,21 +29,26 @@ export interface StorageConnectorAPI { * @param path * @param stream */ - write(path: string, stream: Stream, options?: WriteOptions): Promise; + write( + path: string, + stream: Stream, + options?: WriteOptions, + context?: ExecutionContext, + ): Promise; /** * Read a path and returns its stream * * @param path */ - read(path: string, options?: ReadOptions): Promise; + read(path: string, options?: ReadOptions, context?: ExecutionContext): Promise; /** * Remove a path * * @param path */ - remove(path: string, options?: DeleteOptions): Promise; + remove(path: string, options?: DeleteOptions, context?: ExecutionContext): Promise; } export default interface StorageAPI extends TwakeServiceProvider, StorageConnectorAPI { diff --git a/twake/backend/node/src/core/platform/services/tracker/adapters/segment.ts b/twake/backend/node/src/core/platform/services/tracker/adapters/segment.ts index 21b2c2d830..06f949e38c 100644 --- a/twake/backend/node/src/core/platform/services/tracker/adapters/segment.ts +++ b/twake/backend/node/src/core/platform/services/tracker/adapters/segment.ts @@ -1,10 +1,9 @@ import Analytics from "analytics-node"; import { Analytics as AnalyticsAbtract } from "./types"; import axios, { AxiosInstance } from "axios"; -import { string } from "yargs"; export default class Segment implements AnalyticsAbtract { - protected version: string = "5.0.0"; //Segment analytics lib version + protected version = "5.0.0"; //Segment analytics lib version protected analytics: Analytics; protected axiosInstance: AxiosInstance; @@ -78,6 +77,7 @@ export default class Segment implements AnalyticsAbtract { }, req, ) + // eslint-disable-next-line @typescript-eslint/no-empty-function .then(() => () => {}) .catch(err => { if (err.response) { diff --git a/twake/backend/node/src/core/platform/services/tracker/index.ts b/twake/backend/node/src/core/platform/services/tracker/index.ts index 7e61203ad7..c89c71d951 100644 --- a/twake/backend/node/src/core/platform/services/tracker/index.ts +++ b/twake/backend/node/src/core/platform/services/tracker/index.ts @@ -2,7 +2,7 @@ import Segment from "./adapters/segment"; import { Analytics } from "./adapters/types"; import { Consumes, TwakeService, logger } from "../../framework"; import TrackerAPI from "./provider"; -import { localEventBus } from "../../framework/pubsub"; +import { localEventBus } from "../../framework/event-bus"; import { IdentifyObjectType, TrackedEventType, TrackerConfiguration } from "./types"; import { ResourceEventsPayload } from "../../../../utils/types"; import { md5 } from "../../../../core/crypto"; diff --git a/twake/backend/node/src/core/platform/services/webserver/error.ts b/twake/backend/node/src/core/platform/services/webserver/error.ts index 82a89e8b9c..f3a0327916 100644 --- a/twake/backend/node/src/core/platform/services/webserver/error.ts +++ b/twake/backend/node/src/core/platform/services/webserver/error.ts @@ -2,8 +2,18 @@ import { FastifyInstance } from "fastify"; function serverErrorHandler(server: FastifyInstance): void { server.setErrorHandler(async (err, request, reply) => { - server.log.debug(err.toString()); - await reply.status(500).send(err); + console.error(`Got ${reply.statusCode} error on request ${request.id} : `, err); + server.log.debug(`Got ${reply.statusCode} error on request ${request.id} : ${err.toString()}`); + await reply.send( + reply.statusCode == 500 + ? { + statusCode: reply.statusCode, + error: "Internal Server Error", + message: "Something went wrong", + requestId: request.id, + } + : err, + ); }); } diff --git a/twake/backend/node/src/core/platform/services/webserver/index.ts b/twake/backend/node/src/core/platform/services/webserver/index.ts index 7aab04b6c8..ed347e3c03 100644 --- a/twake/backend/node/src/core/platform/services/webserver/index.ts +++ b/twake/backend/node/src/core/platform/services/webserver/index.ts @@ -3,8 +3,8 @@ import { Server, IncomingMessage, ServerResponse } from "http"; import { FastifyInstance, fastify } from "fastify"; import sensible from "fastify-sensible"; import multipart from "fastify-multipart"; -import formbody from "fastify-formbody"; -import fastifyStatic from "fastify-static"; +import formbody from "@fastify/formbody"; +import fastifyStatic from "@fastify/static"; import corsPlugin, { FastifyCorsOptions } from "fastify-cors"; import { serverErrorHandler } from "./error"; import WebServerAPI from "./provider"; @@ -12,16 +12,24 @@ import jwtPlugin from "../auth/web/jwt"; import path from "path"; import swaggerPlugin from "fastify-swagger"; import { SkipCLI } from "../../framework/decorators/skip"; +import fs from "fs"; // import { throws } from "assert"; export default class WebServerService extends TwakeService implements WebServerAPI { name = "webserver"; version = "1"; private server: FastifyInstance; + // eslint-disable-next-line @typescript-eslint/ban-types + private onReadyHandlers: Function[] = []; getServer(): FastifyInstance { return this.server; } + // eslint-disable-next-line @typescript-eslint/ban-types + onReady(handler: Function): void { + this.onReadyHandlers.push(handler); + } + api(): WebServerAPI { return this; } @@ -38,6 +46,25 @@ export default class WebServerService extends TwakeService impleme done(); }); + this.server.addHook("onError", (request, reply, error, done) => { + logger.error(error); + done(); + }); + + this.server.addHook("preValidation", (request, reply, done) => { + if (reply.statusCode === 500) { + logger.error("An error occured with the preValidation of ", request.routerPath); + } + done(); + }); + + this.server.addHook("preHandler", (request, reply, done) => { + if (reply.statusCode === 500) { + logger.error("An error occured with the preHandler of ", request.routerPath); + } + done(); + }); + serverErrorHandler(this.server); // DIRTY HACK: THis needs to be registered here to avoid circular dep between auth and user. // will have to create a core service for this, or another service which must be started first... @@ -70,27 +97,49 @@ export default class WebServerService extends TwakeService impleme exposeRoute: true, }); this.server.register(jwtPlugin); - this.server.register(sensible); + this.server.register(sensible, { errorHandler: false }); this.server.register(multipart); this.server.register(formbody); this.server.register(corsPlugin, this.configuration.get("cors", {})); - const root = this.configuration.get<{ root: string }>("static", { root: "./public" }).root; - this.server.register(fastifyStatic, { - root: root.indexOf("/") === 0 ? root : path.join(__dirname + "/../../../../../", root), - }); - return this; } @SkipCLI() async doStart(): Promise { try { + let root = this.configuration.get<{ root: string }>("static", { root: "./public" }).root; + root = root.indexOf("/") === 0 ? root : path.join(__dirname + "/../../../../../", root); + this.server.register(fastifyStatic, { + root, + }); + this.server.setNotFoundHandler((req, res) => { + if ( + req.raw.url && + (req.raw.url.startsWith("/internal") || + req.raw.url.startsWith("/api") || + req.raw.url.startsWith("/plugins") || + req.raw.url.startsWith("/admin")) + ) { + return res.status(404).send({ + error: "Not found", + }); + } + + const path = root.replace(/\/$/, "") + "/index.html"; + const stream = fs.createReadStream(path); + res.type("text/html").send(stream); + }); + await this.server.listen(this.configuration.get("port", 3000), "0.0.0.0"); this.server.ready(err => { if (err) throw err; this.server.swagger(); + + this.onReadyHandlers.forEach(handler => { + handler(err); + }); }); return this; diff --git a/twake/backend/node/src/core/platform/services/webserver/provider.ts b/twake/backend/node/src/core/platform/services/webserver/provider.ts index 79cbf5fd7d..aa7d8b4f87 100644 --- a/twake/backend/node/src/core/platform/services/webserver/provider.ts +++ b/twake/backend/node/src/core/platform/services/webserver/provider.ts @@ -7,4 +7,7 @@ export default interface WebServerAPI extends TwakeServiceProvider { * Get the fastify webserver instance */ getServer(): FastifyInstance; + + // eslint-disable-next-line @typescript-eslint/ban-types + onReady(handler: Function): void; } diff --git a/twake/backend/node/src/core/platform/services/webserver/types.ts b/twake/backend/node/src/core/platform/services/webserver/types.ts index 909a951956..c725c7339c 100644 --- a/twake/backend/node/src/core/platform/services/webserver/types.ts +++ b/twake/backend/node/src/core/platform/services/webserver/types.ts @@ -8,7 +8,7 @@ export interface CrudController< GetResponseType, SaveResponseType, ListResponseType, - DeleteResponseType + DeleteResponseType, > { get?: CrudHandler; save?: CrudHandler; diff --git a/twake/backend/node/src/core/platform/services/websocket/index.ts b/twake/backend/node/src/core/platform/services/websocket/index.ts index 9f07c66a49..d039796f0b 100644 --- a/twake/backend/node/src/core/platform/services/websocket/index.ts +++ b/twake/backend/node/src/core/platform/services/websocket/index.ts @@ -1,10 +1,9 @@ -import { IOptions as SocketIOJWTOptions } from "socketio-jwt"; import { Consumes, ServiceName, TwakeService } from "../../framework"; import WebServerAPI from "../webserver/provider"; import WebSocketAPI from "./provider"; -import websocketPlugin from "./plugin"; import { WebSocketService } from "./services"; import { AdaptersConfiguration } from "./types"; +import FastifyIO from "fastify-socket.io"; @Consumes(["webserver"]) @ServiceName("websocket") @@ -18,19 +17,29 @@ export default class WebSocket extends TwakeService { } async doInit(): Promise { - const fastify = this.context.getProvider("webserver").getServer(); + const webserver = this.context.getProvider("webserver"); + const fastify = webserver.getServer(); - this.service = new WebSocketService({ - server: fastify.server, - options: { - path: this.configuration.get("path", "/socket"), + const options = { + path: this.configuration.get("path", "/socket"), + }; + + fastify.register(FastifyIO, { + ...options, + allowEIO3: true, + cors: { + //Allow all origins + origin: (origin, callback) => callback(null, origin), + credentials: true, }, - adapters: this.configuration.get("adapters"), - auth: this.configuration.get("auth.jwt"), }); - fastify.register(websocketPlugin, { - io: this.service.getIo(), + this.service = new WebSocketService({ + server: fastify, + options, + ready: webserver.onReady.bind(webserver), + adapters: this.configuration.get("adapters"), + auth: this.configuration.get<{ secret: string }>("auth.jwt"), }); return this; diff --git a/twake/backend/node/src/core/platform/services/websocket/plugin.ts b/twake/backend/node/src/core/platform/services/websocket/plugin.ts deleted file mode 100644 index f462414f7d..0000000000 --- a/twake/backend/node/src/core/platform/services/websocket/plugin.ts +++ /dev/null @@ -1,13 +0,0 @@ -import socketIO from "socket.io"; -import { FastifyPluginCallback } from "fastify"; -import fp from "fastify-plugin"; - -const socketIOPlugin: FastifyPluginCallback<{ io: socketIO.Server }> = (fastify, opts, next) => { - fastify.decorate("io", opts.io); - - next(); -}; - -export default fp(socketIOPlugin, { - name: "fastify-socketio", -}); diff --git a/twake/backend/node/src/core/platform/services/websocket/services/index.ts b/twake/backend/node/src/core/platform/services/websocket/services/index.ts index d1f85563b5..88f34f9655 100644 --- a/twake/backend/node/src/core/platform/services/websocket/services/index.ts +++ b/twake/backend/node/src/core/platform/services/websocket/services/index.ts @@ -1,6 +1,8 @@ -import socketIO from "socket.io"; -import SocketIORedis from "socket.io-redis"; -import socketIOJWT from "socketio-jwt"; +import socketIO, { Server } from "socket.io"; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { createClient } = require("redis"); +import SocketIORedis from "@socket.io/redis-adapter"; +import jwt from "jsonwebtoken"; import WebSocketAPI from "../provider"; import { WebSocket, @@ -10,6 +12,7 @@ import { } from "../types"; import { EventEmitter } from "events"; import { User } from "../../../../../utils/types"; +import { JwtType } from "../../types"; export class WebSocketService extends EventEmitter implements WebSocketAPI { version: "1"; @@ -17,37 +20,60 @@ export class WebSocketService extends EventEmitter implements WebSocketAPI { constructor(serviceConfiguration: WebSocketServiceConfiguration) { super(); - this.io = socketIO(serviceConfiguration.server, serviceConfiguration.options); - if (serviceConfiguration.adapters?.types?.includes("redis")) { - this.io.adapter(SocketIORedis(serviceConfiguration.adapters.redis)); - } + serviceConfiguration.ready(() => { + this.io = serviceConfiguration.server.io; - this.io.sockets - .on( - "connection", - socketIOJWT.authorize({ - secret: serviceConfiguration.auth.secret, - timeout: 15000, - }), - ) - .on("authenticated", (socket: WebSocket) => { - const user = this.getUser(socket); + if (serviceConfiguration.adapters?.types?.includes("redis")) { + const pubClient = createClient(serviceConfiguration.adapters.redis); + const subClient = pubClient.duplicate(); + this.io.adapter(SocketIORedis.createAdapter(pubClient, subClient)); + } - this.emit("user:connected", { - user, - socket, - event: "user:connected", - } as WebsocketUserEvent); + this.io.on("connection", socket => { + socket.on("authenticate", message => { + if (message.token) { + jwt.verify( + message.token as string, + serviceConfiguration.auth.secret as string, + (err, decoded) => { + if (err) { + socket.emit("unauthorized", { err }); + socket.disconnect(); + return; + } + (socket as unknown as WebSocket).decoded_token = decoded as JwtType; + const user = this.getUser(socket as WebSocket); - socket.on("disconnect", () => - this.emit("user:disconnected", { - user, - socket, - event: "user:disconnected", - } as WebsocketUserEvent), - ); + socket.emit("authenticated"); + + socket.on("message", message => { + this.io.emit("message", message); + }); + + this.emit("user:connected", { + user, + socket, + event: "user:connected", + } as WebsocketUserEvent); + + socket.on("disconnect", () => + this.emit("user:disconnected", { + user, + socket, + event: "user:disconnected", + } as WebsocketUserEvent), + ); + }, + ); + } else { + socket.emit("unauthorized", { err: "No token provided" }); + socket.disconnect(); + return; + } + }); }); + }); } onUserConnected(listener: (event: WebsocketUserEvent) => void): this { diff --git a/twake/backend/node/src/core/platform/services/websocket/types.ts b/twake/backend/node/src/core/platform/services/websocket/types.ts index 56da8a8a9d..6df3dd3d9c 100644 --- a/twake/backend/node/src/core/platform/services/websocket/types.ts +++ b/twake/backend/node/src/core/platform/services/websocket/types.ts @@ -1,21 +1,21 @@ -import { Server as HttpServer } from "http"; -import { Server as HttpsServer } from "https"; -import { IOptions as SocketIOJWTOptions } from "socketio-jwt"; -import socketIO from "socket.io"; -import SocketIORedis from "socket.io-redis"; +import socketIO, { Socket } from "socket.io"; +import { RedisAdapterOptions } from "@socket.io/redis-adapter"; import { User } from "../../../../utils/types"; import { JwtType } from "../types"; +import { FastifyInstance } from "fastify"; export interface AdaptersConfiguration { types: Array; - redis: SocketIORedis.SocketIORedisOptions; + redis: RedisAdapterOptions; } export interface WebSocketServiceConfiguration { - server: HttpServer | HttpsServer; - options?: socketIO.ServerOptions; + server: FastifyInstance; + // eslint-disable-next-line @typescript-eslint/ban-types + ready: Function; + options?: socketIO.ServerOptions | { path: string }; adapters?: AdaptersConfiguration; - auth?: SocketIOJWTOptions; + auth?: { secret: string }; } export interface WebSocketUser extends User { @@ -26,7 +26,7 @@ export interface WebSockets { [index: string]: WebSocket[]; } -export interface WebSocket extends SocketIO.Socket { +export interface WebSocket extends Socket { decoded_token: DecodedToken; } diff --git a/twake/backend/node/src/server.ts b/twake/backend/node/src/server.ts index c403a9db9d..ef38dee78f 100644 --- a/twake/backend/node/src/server.ts +++ b/twake/backend/node/src/server.ts @@ -12,4 +12,5 @@ if (config.get("sentry.dsn")) { const launch = async (): Promise => twake.run(config.get("services")); +// noinspection JSIgnoredPromiseFromCall launch(); diff --git a/twake/backend/node/src/services/applications-api/index.ts b/twake/backend/node/src/services/applications-api/index.ts new file mode 100644 index 0000000000..5343ad5a1c --- /dev/null +++ b/twake/backend/node/src/services/applications-api/index.ts @@ -0,0 +1,34 @@ +import { Prefix, TwakeService } from "../../core/platform/framework"; +import WebServerAPI from "../../core/platform/services/webserver/provider"; +import web from "./web/index"; +import FastProxy from "fast-proxy"; + +@Prefix("/api") +export default class ApplicationsApiService extends TwakeService { + version = "1"; + name = "applicationsapi"; + + public async doInit(): Promise { + const fastify = this.context.getProvider("webserver").getServer(); + fastify.register((instance, _opts, next) => { + web(instance, { prefix: this.prefix }); + next(); + }); + + //Redirect requests from /plugins/* to the plugin server (if installed) + const { proxy, close } = FastProxy({ + base: this.configuration.get("plugins.server"), + }); + fastify.addHook("onClose", close); + fastify.all("/plugins/*", (req, rep) => { + proxy(req.raw, rep.raw, req.url, {}); + }); + + return this; + } + + // TODO: remove + api(): undefined { + return undefined; + } +} diff --git a/twake/backend/node/src/services/applications-api/types.ts b/twake/backend/node/src/services/applications-api/types.ts new file mode 100644 index 0000000000..9919e15d5c --- /dev/null +++ b/twake/backend/node/src/services/applications-api/types.ts @@ -0,0 +1,13 @@ +import { Channel } from "../channels/entities"; +import { Message } from "../messages/entities/messages"; +import { Thread } from "../messages/entities/threads"; + +export type HookType = { + type: "message"; + application_id: string; + company_id: string; + + channel?: Channel; + thread: Thread; + message: Message; +}; diff --git a/twake/backend/node/src/services/applications-api/web/controllers/index.ts b/twake/backend/node/src/services/applications-api/web/controllers/index.ts new file mode 100644 index 0000000000..cb7378ce64 --- /dev/null +++ b/twake/backend/node/src/services/applications-api/web/controllers/index.ts @@ -0,0 +1,173 @@ +import { FastifyInstance, FastifyReply, FastifyRequest, HTTPMethods } from "fastify"; +import { ApplicationObject } from "../../../applications/entities/application"; +import { + ApplicationApiExecutionContext, + ApplicationLoginRequest, + ApplicationLoginResponse, + ConfigureRequest, +} from "../types"; +import { ResourceGetResponse } from "../../../../utils/types"; +import { CrudException } from "../../../../core/platform/framework/api/crud-service"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; +import { + RealtimeApplicationEvent, + RealtimeBaseBusEvent, +} from "../../../../core/platform/services/realtime/types"; +import gr from "../../../global-resolver"; +import _ from "lodash"; +import { v4 } from "uuid"; + +export class ApplicationsApiController { + async token( + request: FastifyRequest<{ Body: ApplicationLoginRequest }>, + ): Promise> { + const context = getExecutionContext(request); + const app = await gr.services.applications.marketplaceApps.get( + { + id: request.body.id, + }, + context, + ); + + if (!app) { + throw CrudException.forbidden("Application not found"); + } + + if (app.api.private_key !== request.body.secret) { + throw CrudException.forbidden("Secret key is not valid"); + } + + return { + resource: { + access_token: gr.platformServices.auth.generateJWT(request.body.id, null, { + track: false, + provider_id: "", + application_id: request.body.id, + }), + }, + }; + } + + async me( + request: FastifyRequest, + reply: FastifyReply, + ): Promise> { + const context = getExecutionContext(request); + + const entity = await gr.services.applications.marketplaceApps.get( + { + id: context.application_id, + }, + context, + ); + if (!entity) { + throw CrudException.notFound("Application not found"); + } + + return { resource: entity.getApplicationObject() }; + } + + async configure(request: FastifyRequest<{ Body: ConfigureRequest }>, reply: FastifyReply) { + const app_id = request.currentUser.application_id; + const context = getExecutionContext(request); + const application = await gr.services.applications.marketplaceApps.get({ id: app_id }, context); + + if (!application) { + throw CrudException.forbidden("Application not found"); + } + + const body = request.body; + + const data = { + action: "configure", + application: { + id: app_id, + identity: application.identity, + }, + form: body.form, + connection_id: body.connection_id, + hidden_data: {}, + configurator_id: v4(), + }; + + localEventBus.publish("realtime:event", { + room: "/me/" + body.user_id, + type: "application", + data, + } as RealtimeBaseBusEvent); + + return { status: "ok" }; + } + + async proxy( + request: FastifyRequest<{ Params: { company_id: string; service: string; version: string } }>, + reply: FastifyReply, + fastify: FastifyInstance, + ) { + // Check the application has access to this company + const company_id = request.params.company_id; + const companyApplication = gr.services.applications.companyApps.get({ + company_id, + application_id: request.currentUser.application_id, + id: undefined, + }); + if (!companyApplication) { + throw CrudException.forbidden("This application is not installed in the requested company"); + } + + const context = getExecutionContext(request); + const app = await gr.services.applications.marketplaceApps.get( + { + id: request.currentUser.application_id, + }, + context, + ); + + // Check call can be done from this IP + if ( + app.api.allowed_ips.trim() && + app.api.allowed_ips !== "*" && + !_.includes( + app.api.allowed_ips + .split(",") + .map(a => a.trim()) + .filter(a => a), + request.ip, + ) + ) { + throw CrudException.forbidden( + `This application is not allowed to access from this IP (${request.ip})`, + ); + } + + //TODO Check application access rights (write, read, remove for each micro services) + const access = app.access; + + //TODO save some statistics about API usage for application and per companies + + const route = request.url.replace("/api/", "/internal/services/"); + + fastify.inject( + { + method: request.method as HTTPMethods, + url: route, + payload: request.body as any, + headers: _.pick(request.headers, "authorization"), + }, + (err, response) => { + reply.headers(response.headers); + reply.send(response.payload); + }, + ); + } +} + +function getExecutionContext(request: FastifyRequest): ApplicationApiExecutionContext { + return { + application_id: request.currentUser?.application_id, + user: request.currentUser, + url: request.url, + method: request.routerMethod, + transport: "http", + }; +} diff --git a/twake/backend/node/src/services/applications-api/web/index.ts b/twake/backend/node/src/services/applications-api/web/index.ts new file mode 100644 index 0000000000..de7176c9f6 --- /dev/null +++ b/twake/backend/node/src/services/applications-api/web/index.ts @@ -0,0 +1,10 @@ +import { FastifyInstance, FastifyRegisterOptions } from "fastify"; +import routes from "./routes"; + +export default ( + fastify: FastifyInstance, + options: FastifyRegisterOptions<{ prefix: string }>, +): void => { + fastify.log.debug("Configuring /internal/services/applications/v1 routes"); + fastify.register(routes, options); +}; diff --git a/twake/backend/node/src/services/applications-api/web/routes.ts b/twake/backend/node/src/services/applications-api/web/routes.ts new file mode 100644 index 0000000000..3af81dbb61 --- /dev/null +++ b/twake/backend/node/src/services/applications-api/web/routes.ts @@ -0,0 +1,54 @@ +import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify"; + +import { ApplicationsApiController } from "./controllers"; +import { ApplicationApiBaseRequest } from "./types"; +import { logger as log } from "../../../core/platform/framework"; +import { configureRequestSchema } from "./schemas"; + +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const controller = new ApplicationsApiController(); + + const checkApplication = async (request: FastifyRequest<{ Body: ApplicationApiBaseRequest }>) => { + if (!request.currentUser.application_id) { + log.debug(request.currentUser); + throw fastify.httpErrors.forbidden("You should log in as application"); + } + }; + + //Authenticate the application + fastify.route({ + method: "POST", + url: "/console/v1/login", + handler: controller.token.bind(controller), + }); + + //Get myself as an application + fastify.route({ + method: "GET", + url: "/console/v1/me", + preValidation: [fastify.authenticate], + preHandler: [checkApplication], + handler: controller.me.bind(controller), + }); + + //Open a configuration popup on the client side + fastify.route({ + method: "POST", + url: "/console/v1/configure", + preValidation: [fastify.authenticate], + schema: configureRequestSchema, + handler: controller.configure.bind(controller), + }); + + //Get myself as an application + fastify.route({ + method: ["POST", "GET", "DELETE", "PUT"], + url: "/:service/:version/companies/:company_id/*", + preValidation: [fastify.authenticate], + handler: (request, reply) => controller.proxy.bind(controller)(request, reply, fastify), + }); + + next(); +}; + +export default routes; diff --git a/twake/backend/node/src/services/applications-api/web/schemas.ts b/twake/backend/node/src/services/applications-api/web/schemas.ts new file mode 100644 index 0000000000..1ee1b3706a --- /dev/null +++ b/twake/backend/node/src/services/applications-api/web/schemas.ts @@ -0,0 +1,16 @@ +export const applicationsSchema = { + type: "object", + properties: {}, +}; + +export const configureRequestSchema = { + body: { + type: "object", + properties: { + user_id: { type: "string" }, + connection_id: { type: "string" }, + form: {}, + }, + required: ["user_id", "connection_id"], + }, +}; diff --git a/twake/backend/node/src/services/applications-api/web/types.ts b/twake/backend/node/src/services/applications-api/web/types.ts new file mode 100644 index 0000000000..04556d9e69 --- /dev/null +++ b/twake/backend/node/src/services/applications-api/web/types.ts @@ -0,0 +1,23 @@ +import { AccessToken } from "../../../utils/types"; +import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; + +export interface ApplicationApiBaseRequest { + id: string; + secret: string; +} + +export type ApplicationLoginRequest = ApplicationApiBaseRequest; + +export interface ApplicationLoginResponse { + access_token: AccessToken; +} + +export interface ApplicationApiExecutionContext extends ExecutionContext { + application_id: string; +} + +export interface ConfigureRequest { + user_id: string; + connection_id: string; + form?: any; +} diff --git a/twake/backend/node/src/services/applications/api.ts b/twake/backend/node/src/services/applications/api.ts deleted file mode 100644 index cfcffc537f..0000000000 --- a/twake/backend/node/src/services/applications/api.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { - DeleteResult, - ExecutionContext, - ListResult, - Paginable, - Pagination, - SaveResult, -} from "../../core/platform/framework/api/crud-service"; -import { CRUDService } from "../../core/platform/framework/api/crud-service"; -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; -import Application, { - ApplicationPrimaryKey, - PublicApplicationObject, -} from "./entities/application"; -import { CompanyExecutionContext } from "./web/types"; -import { - CompanyApplicationPrimaryKey, - CompanyApplicationWithApplication, -} from "./entities/company-application"; -import { CompaniesServiceAPI } from "../user/api"; -import { uuid } from "../../utils/types"; - -export interface ApplicationServiceAPI extends TwakeServiceProvider, Initializable { - applications: MarketplaceApplicationServiceAPI; - companyApplications: CompanyApplicationServiceAPI; - companies: CompaniesServiceAPI; -} - -export interface MarketplaceApplicationServiceAPI extends TwakeServiceProvider, Initializable { - get(pk: ApplicationPrimaryKey, context?: ExecutionContext): Promise; - - listUnpublished(): Promise; - - list( - pagination: Paginable, - options?: ListOptions, - context?: ExecutionContext, - ): Promise>; - - save( - item: Application, - options?: SaveOptions, - context?: ExecutionContext, - ): Promise>; - - listDefaults( - pagination?: Pagination, - options?: ListOptions, - context?: ExecutionContext, - ): Promise>; - - publish(pk: ApplicationPrimaryKey): Promise; - unpublish(pk: ApplicationPrimaryKey): Promise; -} - -export interface CompanyApplicationServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService< - CompanyApplicationWithApplication, - CompanyApplicationPrimaryKey, - CompanyExecutionContext - > { - initWithDefaultApplications(companyId: string, context: CompanyExecutionContext): Promise; - - save( - item: Pick, - _?: SaveOptions, - context?: CompanyExecutionContext, - ): Promise>; - - get( - item: Pick, - context?: CompanyExecutionContext, - ): Promise; - - delete( - item: Pick, - context?: CompanyExecutionContext, - ): Promise>; -} diff --git a/twake/backend/node/src/services/applications/entities/application.search.ts b/twake/backend/node/src/services/applications/entities/application.search.ts index 922ca9cc3a..669e024542 100644 --- a/twake/backend/node/src/services/applications/entities/application.search.ts +++ b/twake/backend/node/src/services/applications/entities/application.search.ts @@ -1,4 +1,3 @@ -import { expandStringForPrefix } from "../../../core/platform/services/search/adapters/utils"; import Application, { TYPE } from "./application"; export default { @@ -7,31 +6,28 @@ export default { return { company_id: entity.company_id, name: entity.identity.name, - expanded_name: expandStringForPrefix(entity.identity.name), description: entity.identity.description, categories: entity.identity.categories, compatibility: entity.identity.compatibility, published: entity.publication.published, - createdAt: entity.stats.createdAt, + created_at: entity.stats.created_at, }; }, mongoMapping: { text: { name: "text", - expanded_name: "text", description: "text", }, }, esMapping: { properties: { company_id: { type: "keyword" }, - name: { type: "text" }, - expanded_name: { type: "text" }, + name: { type: "text", index_prefixes: { min_chars: 1 } }, description: { type: "text" }, categories: { type: "keyword" }, compatibility: { type: "keyword" }, published: { type: "boolean" }, - createdAt: { type: "number" }, + created_at: { type: "number" }, }, }, }; diff --git a/twake/backend/node/src/services/applications/entities/application.ts b/twake/backend/node/src/services/applications/entities/application.ts index fb78603c6d..17cf4f5422 100644 --- a/twake/backend/node/src/services/applications/entities/application.ts +++ b/twake/backend/node/src/services/applications/entities/application.ts @@ -117,15 +117,15 @@ export type ApplicationPublication = { }; export type ApplicationStatistics = { - createdAt: number; // RO - updatedAt: number; // RO + created_at: number; // RO + updated_at: number; // RO version: number; // RO }; export type ApplicationApi = { - hooksUrl: string; - allowedIps: string; - privateKey: string; // RO + hooks_url: string; + allowed_ips: string; + private_key: string; // RO }; type ApplicationScopes = diff --git a/twake/backend/node/src/services/applications/entities/company-application.ts b/twake/backend/node/src/services/applications/entities/company-application.ts index 4a408307d8..7598e05fd1 100644 --- a/twake/backend/node/src/services/applications/entities/company-application.ts +++ b/twake/backend/node/src/services/applications/entities/company-application.ts @@ -1,6 +1,6 @@ import { Type } from "class-transformer"; import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; -import Application, { PublicApplicationObject } from "./application"; +import { PublicApplicationObject } from "./application"; export const TYPE = "group_app"; diff --git a/twake/backend/node/src/services/applications/index.ts b/twake/backend/node/src/services/applications/index.ts index 5b9809dc94..7c73c6a82a 100644 --- a/twake/backend/node/src/services/applications/index.ts +++ b/twake/backend/node/src/services/applications/index.ts @@ -1,34 +1,24 @@ -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { ApplicationServiceAPI } from "./api"; -import { getService } from "./services/index"; -import web from "./web/index"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import UserServiceAPI from "../user/api"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; +import { Prefix, TwakeService } from "../../core/platform/framework"; +import WebServerAPI from "../../core/platform/services/webserver/provider"; +import web from "./web"; @Prefix("/internal/services/applications/v1") -@Consumes(["platform-services", "realtime"]) -export default class ApplicationsService extends TwakeService { +export default class ApplicationsService extends TwakeService { version = "1"; name = "applications"; - service: ApplicationServiceAPI; - - api(): ApplicationServiceAPI { - return this.service; - } public async doInit(): Promise { - const platformServices = this.context.getProvider("platform-services"); - const fastify = platformServices.fastify.getServer(); - this.service = getService(platformServices, null); - const realtime = this.context.getProvider("realtime"); - await this.service.init(this.context); - + const fastify = this.context.getProvider("webserver").getServer(); fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + web(instance, { prefix: this.prefix }); next(); }); return this; } + + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/applications/services/applications.ts b/twake/backend/node/src/services/applications/services/applications.ts index 2fb378deb2..ef9477c707 100644 --- a/twake/backend/node/src/services/applications/services/applications.ts +++ b/twake/backend/node/src/services/applications/services/applications.ts @@ -1,4 +1,3 @@ -import { MarketplaceApplicationServiceAPI } from "../api"; import Application, { ApplicationPrimaryKey, getInstance as getApplicationInstance, @@ -6,51 +5,45 @@ import Application, { TYPE, } from "../entities/application"; import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; -import { logger } from "../../../core/platform/framework"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; +import { Initializable, logger, TwakeServiceProvider } from "../../../core/platform/framework"; import { - CreateResult, DeleteResult, ExecutionContext, ListResult, OperationType, Pagination, SaveResult, - UpdateResult, } from "../../../core/platform/framework/api/crud-service"; import SearchRepository from "../../../core/platform/services/search/repository"; import assert from "assert"; -export function getService(platformService: PlatformServicesAPI): MarketplaceApplicationServiceAPI { - return new ApplicationService(platformService); -} +import gr from "../../global-resolver"; +import { InternalToHooksProcessor } from "./internal-event-to-hooks"; -class ApplicationService implements MarketplaceApplicationServiceAPI { +export class ApplicationServiceImpl implements TwakeServiceProvider, Initializable { version: "1"; repository: Repository; searchRepository: SearchRepository; - constructor(readonly platformService: PlatformServicesAPI) {} - async init(): Promise { try { - this.searchRepository = this.platformService.search.getRepository( - TYPE, - Application, - ); - this.repository = await this.platformService.database.getRepository( + this.searchRepository = gr.platformServices.search.getRepository( TYPE, Application, ); + this.repository = await gr.database.getRepository(TYPE, Application); } catch (err) { console.log(err); logger.error("Error while initializing applications service"); } + + gr.platformServices.messageQueue.processor.addHandler(new InternalToHooksProcessor()); + return this; } - async get(pk: ApplicationPrimaryKey, context?: ExecutionContext): Promise { - return await this.repository.findOne(pk); + async get(pk: ApplicationPrimaryKey, context: ExecutionContext): Promise { + return await this.repository.findOne(pk, {}, context); } async list( @@ -68,9 +61,10 @@ class ApplicationService implements MarketplaceApplicationServiceAPI { $search: options.search, }, }, + context, ); } else { - entities = await this.repository.find({}, { pagination }); + entities = await this.repository.find({}, { pagination }, context); } entities.filterEntities(app => app.publication.published); @@ -81,24 +75,20 @@ class ApplicationService implements MarketplaceApplicationServiceAPI { return new ListResult(entities.type, applications, entities.nextPage); } - async listUnpublished(): Promise { - const entities = await this.repository.find({}, {}); + async listUnpublished(context: ExecutionContext): Promise { + const entities = await this.repository.find({}, {}, context); entities.filterEntities(app => !app.publication.published); return entities.getEntities(); } async listDefaults( - pagination: Pagination, - options?: ListOptions, - context?: ExecutionContext, + context: ExecutionContext, ): Promise> { - //Fixme: this is not great if we have a lot of applications in the future - const entities = []; let page: Pagination = { limitStr: "100" }; do { - const applicationListResult = await this.repository.find({}, { pagination: page }); + const applicationListResult = await this.repository.find({}, { pagination: page }, context); page = applicationListResult.nextPage as Pagination; applicationListResult.filterEntities(app => app.publication.published && app.is_default); @@ -119,34 +109,37 @@ class ApplicationService implements MarketplaceApplicationServiceAPI { try { const entity = getApplicationInstance(item); - await this.repository.save(entity); + await this.repository.save(entity, context); return new SaveResult("application", entity, OperationType.UPDATE); } catch (e) { throw e; } } - delete( + + async delete( pk: ApplicationPrimaryKey, context?: ExecutionContext, ): Promise> { - throw new Error("Method not implemented."); + const entity = await this.get(pk, context); + await this.repository.remove(entity, context); + return new DeleteResult("application", entity, true); } - async publish(pk: ApplicationPrimaryKey): Promise { - const entity = await this.get(pk); + async publish(pk: ApplicationPrimaryKey, context: ExecutionContext): Promise { + const entity = await this.get(pk, context); if (!entity) { throw new Error("Entity not found"); } entity.publication.published = true; - await this.repository.save(entity); + await this.repository.save(entity, context); } - async unpublish(pk: ApplicationPrimaryKey): Promise { - const entity = await this.get(pk); + async unpublish(pk: ApplicationPrimaryKey, context: ExecutionContext): Promise { + const entity = await this.get(pk, context); if (!entity) { throw new Error("Entity not found"); } entity.publication.published = false; - await this.repository.save(entity); + await this.repository.save(entity, context); } } diff --git a/twake/backend/node/src/services/applications/services/company-applications.ts b/twake/backend/node/src/services/applications/services/company-applications.ts index b5d398817d..8b461d0cd6 100644 --- a/twake/backend/node/src/services/applications/services/company-applications.ts +++ b/twake/backend/node/src/services/applications/services/company-applications.ts @@ -1,41 +1,35 @@ -import { CompanyApplicationServiceAPI, MarketplaceApplicationServiceAPI } from "../api"; import CompanyApplication, { - TYPE, CompanyApplicationPrimaryKey, CompanyApplicationWithApplication, + TYPE, } from "../entities/company-application"; import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; -import { logger, RealtimeDeleted, RealtimeSaved } from "../../../core/platform/framework"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; +import { + Initializable, + logger, + RealtimeDeleted, + RealtimeSaved, + TwakeServiceProvider, +} from "../../../core/platform/framework"; import { DeleteResult, ListResult, OperationType, + Paginable, Pagination, SaveResult, } from "../../../core/platform/framework/api/crud-service"; import { CompanyExecutionContext } from "../web/types"; import { getCompanyApplicationRoom } from "../realtime"; +import gr from "../../global-resolver"; -export function getService( - platformService: PlatformServicesAPI, - applicationService: MarketplaceApplicationServiceAPI, -): CompanyApplicationServiceAPI { - return new CompanyApplicationService(platformService, applicationService); -} - -class CompanyApplicationService implements CompanyApplicationServiceAPI { +export class CompanyApplicationServiceImpl implements TwakeServiceProvider, Initializable { version: "1"; repository: Repository; - constructor( - readonly platformService: PlatformServicesAPI, - readonly applicationService: MarketplaceApplicationServiceAPI, - ) {} - async init(): Promise { try { - this.repository = await this.platformService.database.getRepository( + this.repository = await gr.database.getRepository( TYPE, CompanyApplication, ); @@ -46,16 +40,26 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { return this; } + // TODO: remove logic from context async get( pk: CompanyApplicationPrimaryKey, context?: CompanyExecutionContext, ): Promise { - const companyApplication = await this.repository.findOne({ - group_id: context.company.id, - app_id: pk.application_id, - }); + const companyApplication = await this.repository.findOne( + { + group_id: context ? context.company.id : pk.company_id, + app_id: pk.application_id, + }, + {}, + context, + ); - const application = await this.applicationService.get({ id: pk.application_id }); + const application = await gr.services.applications.marketplaceApps.get( + { + id: pk.application_id, + }, + context, + ); return { ...companyApplication, @@ -82,10 +86,14 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { } let operation = OperationType.UPDATE; - let companyApplication = await this.repository.findOne({ - group_id: context?.company.id, - app_id: item.application_id, - }); + let companyApplication = await this.repository.findOne( + { + group_id: context?.company.id, + app_id: item.application_id, + }, + {}, + context, + ); if (!companyApplication) { operation = OperationType.CREATE; @@ -95,7 +103,7 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { companyApplication.created_at = new Date().getTime(); companyApplication.created_by = context?.user?.id || ""; - await this.repository.save(companyApplication); + await this.repository.save(companyApplication, context); } return new SaveResult(TYPE, companyApplication, operation); @@ -105,7 +113,7 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { companyId: string, context: CompanyExecutionContext, ): Promise { - const defaultApps = await this.applicationService.listDefaults(); + const defaultApps = await gr.services.applications.marketplaceApps.listDefaults(context); for (const defaultApp of defaultApps.getEntities()) { await this.save({ company_id: companyId, application_id: defaultApp.id }, {}, context); } @@ -124,14 +132,18 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { pk: CompanyApplicationPrimaryKey, context?: CompanyExecutionContext, ): Promise> { - const companyApplication = await this.repository.findOne({ - group_id: context.company.id, - app_id: pk.application_id, - }); + const companyApplication = await this.repository.findOne( + { + group_id: context.company.id, + app_id: pk.application_id, + }, + {}, + context, + ); let deleted = false; if (companyApplication) { - this.repository.remove(companyApplication); + this.repository.remove(companyApplication, context); deleted = true; } @@ -139,7 +151,7 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { } async list( - pagination: Pagination, + pagination: Paginable, options?: ListOptions, context?: CompanyExecutionContext, ): Promise> { @@ -147,15 +159,19 @@ class CompanyApplicationService implements CompanyApplicationServiceAPI { { group_id: context.company.id, }, - { pagination }, + { pagination: Pagination.fromPaginable(pagination) }, + context, ); const applications = []; for (const companyApplication of companyApplications.getEntities()) { - const application = await this.applicationService.get({ - id: companyApplication.application_id, - }); + const application = await gr.services.applications.marketplaceApps.get( + { + id: companyApplication.application_id, + }, + context, + ); if (application) applications.push({ ...companyApplication, diff --git a/twake/backend/node/src/services/applications/services/hooks.ts b/twake/backend/node/src/services/applications/services/hooks.ts new file mode 100644 index 0000000000..d34a5f1559 --- /dev/null +++ b/twake/backend/node/src/services/applications/services/hooks.ts @@ -0,0 +1,96 @@ +import Application from "../entities/application"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { + Initializable, + logger as log, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import { CrudException, ExecutionContext } from "../../../core/platform/framework/api/crud-service"; +import SearchRepository from "../../../core/platform/services/search/repository"; +import axios from "axios"; +import * as crypto from "crypto"; +import { isObject } from "lodash"; +import gr from "../../global-resolver"; + +export class ApplicationHooksService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + searchRepository: SearchRepository; + + async init() { + return this; + } + + async notifyApp( + application_id: string, + connection_id: string, + user_id: string, + type: string, + name: string, + content: any, + company_id: string, + workspace_id: string, + context: ExecutionContext, + ): Promise { + const app = await gr.services.applications.marketplaceApps.get({ id: application_id }, context); + if (!app) { + throw CrudException.notFound("Application not found"); + } + + if (!app.api.hooks_url) { + throw CrudException.badRequest("Application hooks_url is not defined"); + } + + const payload = { + type, + name, + content, + connection_id: connection_id, + user_id: user_id, + company_id, + workspace_id, + }; + + const signature = crypto + .createHmac("sha256", app.api.private_key) + .update(JSON.stringify(payload)) + .digest("hex"); + + return await axios + .post(app.api.hooks_url, payload, { + headers: { + "Content-Type": "application/json", + "X-Twake-Signature": signature, + }, + }) + + .then(({ data }) => data) + .catch(e => { + log.error(e.message); + const r = e.response; + + if (!r) { + throw CrudException.badGateway("Can't connect remote application"); + } + + let msg = r.data; + + if (isObject(msg)) { + // parse typical responses + if (r.data.message) { + msg = r.data.message; + } else if (r.data.error) { + msg = r.data.error; + } else { + msg = JSON.stringify(r.data); + } + } + + if (r.status == 403) { + throw CrudException.forbidden(msg); + } else { + throw CrudException.badRequest(msg); + } + }); + } +} diff --git a/twake/backend/node/src/services/applications/services/index.ts b/twake/backend/node/src/services/applications/services/index.ts deleted file mode 100644 index e17139104e..0000000000 --- a/twake/backend/node/src/services/applications/services/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - ApplicationServiceAPI, - CompanyApplicationServiceAPI, - MarketplaceApplicationServiceAPI, -} from "../api"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; -import { getService as getApplicationService } from "./applications"; -import { getService as getCompanyApplicationService } from "./company-applications"; -import { getService as getCompaniesService } from "../../user/services/companies"; -import UserServiceAPI, { CompaniesServiceAPI } from "../../user/api"; - -export function getService( - platformService: PlatformServicesAPI, - userServiceAPI: UserServiceAPI, -): ApplicationServiceAPI { - return new Service(platformService, userServiceAPI); -} - -class Service { - version: "1"; - applications: MarketplaceApplicationServiceAPI; - companyApplications: CompanyApplicationServiceAPI; - companies: CompaniesServiceAPI; - - constructor(readonly platformService: PlatformServicesAPI, userServiceAPI: UserServiceAPI) { - this.applications = getApplicationService(platformService); - this.companyApplications = getCompanyApplicationService(platformService, this.applications); - this.companies = getCompaniesService(platformService, userServiceAPI); - } - - async init(): Promise { - await this.applications.init(); - await this.companyApplications.init(); - await this.companies.init(); - return this; - } -} diff --git a/twake/backend/node/src/services/applications/services/internal-event-to-hooks.ts b/twake/backend/node/src/services/applications/services/internal-event-to-hooks.ts new file mode 100644 index 0000000000..e2adc4f874 --- /dev/null +++ b/twake/backend/node/src/services/applications/services/internal-event-to-hooks.ts @@ -0,0 +1,64 @@ +import { logger } from "../../../core/platform/framework"; +import { HookType } from "../../applications-api/types"; +import { MessageQueueHandler } from "../../../core/platform/services/message-queue/api"; +import { MessageHook } from "../../messages/types"; +import gr from "../../global-resolver"; +import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; + +export class InternalToHooksProcessor implements MessageQueueHandler { + readonly topics = { + in: "application:hook:message", + }; + + readonly options = { + unique: true, + ack: true, + queue: "application:hook:message:consumer1", + }; + + readonly name = "Application::InternalToHooksProcessor"; + + validate(_: HookType): boolean { + return true; + } + + async process(message: HookType, context?: ExecutionContext): Promise { + logger.debug(`${this.name} - Receive hook of type ${message.type}`); + + const application = await gr.services.applications.marketplaceApps.get( + { + id: message.application_id, + }, + context, + ); + + //TODO Check application access rights (hooks) + const access = application.access; + + // Check application still exists in the company + if ( + !(await gr.services.applications.companyApps.get({ + company_id: message.company_id, + application_id: message.application_id, + id: undefined, + })) + ) { + logger.error( + `${this.name} - Application ${message.application_id} not found in company ${message.company_id}`, + ); + return; + } + + await gr.services.applications.hooks.notifyApp( + message.application_id, + null, + null, + "hook", + null, + { message }, + null, + null, + context, + ); + } +} diff --git a/twake/backend/node/src/services/applications/web/controllers/applications.ts b/twake/backend/node/src/services/applications/web/controllers/applications.ts index 7b36ab3389..9a774a8b39 100644 --- a/twake/backend/node/src/services/applications/web/controllers/applications.ts +++ b/twake/backend/node/src/services/applications/web/controllers/applications.ts @@ -1,8 +1,8 @@ import { FastifyReply, FastifyRequest } from "fastify"; -import { ApplicationServiceAPI } from "../../api"; import { CrudController } from "../../../../core/platform/services/webserver/types"; import { PaginationQueryParameters, + ResourceCreateResponse, ResourceDeleteResponse, ResourceGetResponse, ResourceListResponse, @@ -13,11 +13,16 @@ import Application, { PublicApplicationObject, } from "../../entities/application"; import { - CrudExeption, + CrudException, ExecutionContext, + Pagination, } from "../../../../core/platform/framework/api/crud-service"; import _ from "lodash"; import { randomBytes } from "crypto"; +import { ApplicationEventRequestBody } from "../types"; +import { logger as log } from "../../../../core/platform/framework"; +import { hasCompanyAdminLevel } from "../../../../utils/company"; +import gr from "../../../global-resolver"; export class ApplicationController implements @@ -28,18 +33,19 @@ export class ApplicationController ResourceDeleteResponse > { - constructor(protected service: ApplicationServiceAPI) {} - async get( request: FastifyRequest<{ Params: { application_id: string } }>, ): Promise> { const context = getExecutionContext(request); - const entity = await this.service.applications.get({ - id: request.params.application_id, - }); + const entity = await gr.services.applications.marketplaceApps.get( + { + id: request.params.application_id, + }, + context, + ); - const companyUser = await this.service.companies.getCompanyUser( + const companyUser = await gr.services.companies.getCompanyUser( { id: entity.company_id }, { id: context.user.id }, ); @@ -56,12 +62,9 @@ export class ApplicationController Querystring: PaginationQueryParameters & { search: string }; }>, ): Promise> { - const context = getExecutionContext(request); - const entities = await this.service.applications.list( - request.query, - { search: request.query.search }, - context, - ); + const entities = await gr.services.applications.marketplaceApps.list(new Pagination(), { + search: request.query.search, + }); return { resources: entities.getEntities(), next_page_token: entities.nextPage.page_token, @@ -69,69 +72,85 @@ export class ApplicationController } async save( - request: FastifyRequest<{ Params: { application_id: string }; Body: Application }>, + request: FastifyRequest<{ + Params: { application_id: string }; + Body: { resource: Application }; + }>, reply: FastifyReply, ): Promise> { - // const context = getExecutionContext(request); + const context = getExecutionContext(request); - const app = request.body; - const now = new Date().getTime(); + try { + const app = request.body.resource; + const now = new Date().getTime(); - let entity: Application; + let entity: Application; - if (request.params.application_id) { - entity = await this.service.applications.get({ - id: request.params.application_id, - }); + if (request.params.application_id) { + entity = await gr.services.applications.marketplaceApps.get( + { + id: request.params.application_id, + }, + context, + ); - if (!entity) { - throw CrudExeption.notFound("Application not found"); - } + if (!entity) { + throw CrudException.notFound("Application not found"); + } - entity.publication.requested = app.publication.requested; + entity.publication.requested = app.publication.requested; + if (app.publication.requested === false) { + entity.publication.published = false; + } - if (entity.publication.published) { - if ( - !_.isEqual( - _.pick(entity, "identity", "api", "access", "display"), - _.pick(app, "identity", "api", "access", "display"), - ) - ) { - throw CrudExeption.badRequest("You can't update applications details while it published"); + if (entity.publication.published) { + if ( + !_.isEqual( + _.pick(entity, "identity", "api", "access", "display"), + _.pick(app, "identity", "api", "access", "display"), + ) + ) { + throw CrudException.badRequest( + "You can't update applications details while it published", + ); + } } - } - entity.identity = app.identity; - entity.api.hooksUrl = app.api.hooksUrl; - entity.api.allowedIps = app.api.allowedIps; - entity.access = app.access; - entity.display = app.display; + entity.identity = app.identity; + entity.api.hooks_url = app.api.hooks_url; + entity.api.allowed_ips = app.api.allowed_ips; + entity.access = app.access; + entity.display = app.display; - entity.stats.updatedAt = now; - entity.stats.version++; + entity.stats.updated_at = now; + entity.stats.version++; - const res = await this.service.applications.save(entity); - entity = res.entity; - } else { - // INSERT + const res = await gr.services.applications.marketplaceApps.save(entity); + entity = res.entity; + } else { + // INSERT - app.is_default = false; - app.publication.published = false; - app.api.privateKey = randomBytes(32).toString("base64"); + app.is_default = false; + app.publication.published = false; + app.api.private_key = randomBytes(32).toString("base64"); - app.stats = { - createdAt: now, - updatedAt: now, - version: 0, - }; + app.stats = { + created_at: now, + updated_at: now, + version: 0, + }; - const res = await this.service.applications.save(app); - entity = res.entity; - } + const res = await gr.services.applications.marketplaceApps.save(app); + entity = res.entity; + } - return { - resource: entity.getApplicationObject(), - }; + return { + resource: entity.getApplicationObject(), + }; + } catch (e) { + log.error(e); + throw e; + } } async delete( @@ -139,7 +158,28 @@ export class ApplicationController reply: FastifyReply, ): Promise { const context = getExecutionContext(request); - const deleteResult: any = {}; + + const application = await gr.services.applications.marketplaceApps.get( + { + id: request.params.application_id, + }, + context, + ); + + const compUser = await gr.services.companies.getCompanyUser( + { id: application.company_id }, + { id: context.user.id }, + ); + if (!compUser || !hasCompanyAdminLevel(compUser.role)) { + throw CrudException.forbidden("You don't have the rights to delete this application"); + } + + const deleteResult = await gr.services.applications.marketplaceApps.delete( + { + id: request.params.application_id, + }, + context, + ); if (deleteResult.deleted) { reply.code(204); @@ -154,8 +194,64 @@ export class ApplicationController }; } - async event(request: FastifyRequest<{ Params: { application_id: string } }>) { - return { error: "Not implemented (yet)" }; + async event( + request: FastifyRequest<{ + Body: ApplicationEventRequestBody; + Params: { application_id: string }; + }>, + reply: FastifyReply, + ): Promise> { + const context = getExecutionContext(request); + + const content = request.body.data; + + const applicationEntity = await gr.services.applications.marketplaceApps.get( + { + id: request.params.application_id, + }, + context, + ); + + if (!applicationEntity) { + throw CrudException.notFound("Application not found"); + } + + const companyUser = gr.services.companies.getCompanyUser( + { id: request.body.company_id }, + { id: context.user.id }, + ); + + if (!companyUser) { + throw CrudException.badRequest( + "You cannot send event to an application from another company", + ); + } + + const applicationInCompany = await gr.services.applications.companyApps.get({ + company_id: request.body.company_id, + application_id: request.params.application_id, + id: undefined, + }); + + if (!applicationInCompany) { + throw CrudException.badRequest("Application isn't installed in this company"); + } + + const hookResponse = await gr.services.applications.hooks.notifyApp( + request.params.application_id, + request.body.connection_id, + context.user.id, + request.body.type, + request.body.name, + content, + request.body.company_id, + request.body.workspace_id, + context, + ); + + return { + resource: hookResponse, + }; } } diff --git a/twake/backend/node/src/services/applications/web/controllers/company-applications.ts b/twake/backend/node/src/services/applications/web/controllers/company-applications.ts index 4e6786a4af..1de2e5e6e7 100644 --- a/twake/backend/node/src/services/applications/web/controllers/company-applications.ts +++ b/twake/backend/node/src/services/applications/web/controllers/company-applications.ts @@ -7,12 +7,11 @@ import { ResourceListResponse, ResourceUpdateResponse, } from "../../../../utils/types"; -import Application, { PublicApplicationObject } from "../../entities/application"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import { PublicApplicationObject } from "../../entities/application"; import { CompanyExecutionContext } from "../types"; -import { ApplicationServiceAPI } from "../../api"; import { CrudController } from "../../../../core/platform/services/webserver/types"; import { getCompanyApplicationRooms } from "../../realtime"; +import gr from "../../../global-resolver"; export class CompanyApplicationController implements @@ -23,14 +22,16 @@ export class CompanyApplicationController ResourceDeleteResponse > { - constructor(protected realtime: RealtimeServiceAPI, protected service: ApplicationServiceAPI) {} - async get( request: FastifyRequest<{ Params: { company_id: string; application_id: string } }>, ): Promise> { const context = getCompanyExecutionContext(request); - const resource = await this.service.companyApplications.get( - { application_id: request.params.application_id, company_id: context.company.id }, + const resource = await gr.services.applications.companyApps.get( + { + application_id: request.params.application_id, + company_id: context.company.id, + id: undefined, + }, context, ); return { @@ -45,7 +46,7 @@ export class CompanyApplicationController }>, ): Promise> { const context = getCompanyExecutionContext(request); - const resources = await this.service.companyApplications.list( + const resources = await gr.services.applications.companyApps.list( request.query, { search: request.query.search }, context, @@ -55,7 +56,7 @@ export class CompanyApplicationController resources: resources.getEntities().map(ca => ca.application), next_page_token: resources.nextPage.page_token, websockets: - this.realtime.sign( + gr.platformServices.realtime.sign( getCompanyApplicationRooms(request.params.company_id), context.user.id, ) || [], @@ -70,13 +71,16 @@ export class CompanyApplicationController ): Promise> { const context = getCompanyExecutionContext(request); - const resource = await this.service.companyApplications.save( + const resource = await gr.services.applications.companyApps.save( { application_id: request.params.application_id, company_id: context.company.id }, {}, context, ); + + const app = await gr.services.applications.companyApps.get(resource.entity); + return { - resource: resource.entity.application, + resource: app.application, }; } @@ -85,10 +89,11 @@ export class CompanyApplicationController reply: FastifyReply, ): Promise { const context = getCompanyExecutionContext(request); - const resource = await this.service.companyApplications.delete( - { application_id: request.params.application_id, company_id: context.company.id }, - context, - ); + const resource = await gr.services.applications.companyApps.delete({ + application_id: request.params.application_id, + company_id: context.company.id, + id: undefined, + }); return { status: resource.deleted ? "success" : "error", }; diff --git a/twake/backend/node/src/services/applications/web/index.ts b/twake/backend/node/src/services/applications/web/index.ts index 2f4df4a8a3..3c2df97934 100644 --- a/twake/backend/node/src/services/applications/web/index.ts +++ b/twake/backend/node/src/services/applications/web/index.ts @@ -1,14 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import { ApplicationServiceAPI } from "../api"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: ApplicationServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /internal/services/applications/v1 routes"); diff --git a/twake/backend/node/src/services/applications/web/routes.ts b/twake/backend/node/src/services/applications/web/routes.ts index 8c6f0d9356..3d5835c782 100644 --- a/twake/backend/node/src/services/applications/web/routes.ts +++ b/twake/backend/node/src/services/applications/web/routes.ts @@ -1,44 +1,58 @@ import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import { ApplicationServiceAPI } from "../api"; import { ApplicationController } from "./controllers/applications"; import { CompanyApplicationController } from "./controllers/company-applications"; -import { WorkspaceBaseRequest } from "../../workspaces/web/types"; + import Application from "../entities/application"; -import assert from "assert"; -import { applicationPostSchema } from "./schemas"; +import { applicationEventHookSchema, applicationPostSchema } from "./schemas"; +import { logger as log } from "../../../core/platform/framework"; +import { checkUserBelongsToCompany, hasCompanyAdminLevel } from "../../../utils/company"; +import gr from "../../global-resolver"; const applicationsUrl = "/applications"; const companyApplicationsUrl = "/companies/:company_id/applications"; -const routes: FastifyPluginCallback<{ - service: ApplicationServiceAPI; - realtime: RealtimeServiceAPI; -}> = (fastify: FastifyInstance, options, next) => { - const applicationController = new ApplicationController(options.service); - const companyApplicationController = new CompanyApplicationController( - options.realtime, - options.service, - ); - - const adminCheck = async (request: FastifyRequest<{ Body: Application }>) => { - const companyId = request.body.company_id; - const userId = request.currentUser.id; - assert(companyId, "company_id is not defined"); - const companyUser = await options.service.companies.getCompanyUser( - { id: companyId }, - { id: userId }, - ); - - if (!companyUser) { - const company = await options.service.companies.getCompany({ id: companyId }); - if (!company) { - throw fastify.httpErrors.notFound(`Company ${companyId} not found`); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const applicationController = new ApplicationController(); + const companyApplicationController = new CompanyApplicationController(); + + const adminCheck = async ( + request: FastifyRequest<{ + Body: { resource: Application }; + Params: { application_id: string }; + }>, + ) => { + try { + let companyId: string = request.body?.resource?.company_id; + + if (request.params.application_id) { + const application = await gr.services.applications.marketplaceApps.get( + { + id: request.params.application_id, + }, + undefined, + ); + + if (!application) { + throw fastify.httpErrors.notFound("Application is not defined"); + } + + companyId = application.company_id; } - throw fastify.httpErrors.forbidden("User does not belong to this company"); - } - if (companyUser.role !== "admin") { - throw fastify.httpErrors.forbidden("You must be an admin of this company"); + + const userId = request.currentUser.id; + + if (!companyId) { + throw fastify.httpErrors.forbidden(`Company ${companyId} not found`); + } + + const companyUser = await checkUserBelongsToCompany(userId, companyId); + + if (!hasCompanyAdminLevel(companyUser.role)) { + throw fastify.httpErrors.forbidden("You must be an admin of this company"); + } + } catch (e) { + log.error(e); + throw e; } }; @@ -85,6 +99,15 @@ const routes: FastifyPluginCallback<{ handler: applicationController.save.bind(applicationController), }); + // Delete application (must be my company application and I must be company admin) + fastify.route({ + method: "DELETE", + url: `${applicationsUrl}/:application_id`, + preHandler: [adminCheck], + preValidation: [fastify.authenticate], + handler: applicationController.delete.bind(applicationController), + }); + /** * Company applications collection * Company-wide available applications @@ -128,6 +151,7 @@ const routes: FastifyPluginCallback<{ method: "POST", url: `${applicationsUrl}/:application_id/event`, preValidation: [fastify.authenticate], + schema: applicationEventHookSchema, handler: applicationController.event.bind(applicationController), }); diff --git a/twake/backend/node/src/services/applications/web/schemas.ts b/twake/backend/node/src/services/applications/web/schemas.ts index 7a0cb64b0f..996cea70f1 100644 --- a/twake/backend/node/src/services/applications/web/schemas.ts +++ b/twake/backend/node/src/services/applications/web/schemas.ts @@ -1,5 +1,3 @@ -import { webSocketSchema } from "../../../utils/types"; - export const applicationsSchema = { type: "object", properties: {}, @@ -50,21 +48,21 @@ const responseApplicationPublication = { const applicationStats = { type: "object", properties: { - createdAt: { type: "number" }, - updatedAt: { type: "number" }, + created_at: { type: "number" }, + updated_at: { type: "number" }, version: { type: "number" }, }, - required: ["createdAt", "updatedAt", "version"], + required: ["created_at", "updated_at", "version"], }; const apiObject = { type: "object", properties: { - hooksUrl: { type: "string" }, - allowedIps: { type: "string" }, - privateKey: { type: "string" }, + hooks_url: { type: "string" }, + allowed_ips: { type: "string" }, + private_key: { type: "string" }, }, - required: ["hooksUrl", "allowedIps"], + required: ["hooks_url", "allowed_ips"], }; const requestApplicationObject = { @@ -108,10 +106,24 @@ const responseApplicationObject = { }; export const applicationPostSchema = { - body: requestApplicationObject, + body: { type: "object", properties: { resource: requestApplicationObject } }, response: { "2xx": { resource: responseApplicationObject, }, }, }; + +export const applicationEventHookSchema = { + body: { + type: "object", + properties: { + company_id: { type: "string" }, + workspace_id: { type: "string" }, + type: { type: "string" }, + name: { type: "string" }, + content: {}, + }, + required: ["company_id", "workspace_id", "type", "content"], + }, +}; diff --git a/twake/backend/node/src/services/applications/web/types.ts b/twake/backend/node/src/services/applications/web/types.ts index d340c9c596..5a60f3b3d7 100644 --- a/twake/backend/node/src/services/applications/web/types.ts +++ b/twake/backend/node/src/services/applications/web/types.ts @@ -3,3 +3,13 @@ import { ExecutionContext } from "../../../core/platform/framework/api/crud-serv export interface CompanyExecutionContext extends ExecutionContext { company: { id: string }; } + +export interface ApplicationEventRequestBody { + company_id: string; + workspace_id: string; + connection_id: string; + type: string; + name?: string; + content: any; + data: any; +} diff --git a/twake/backend/node/src/services/applicationsapi/api.ts b/twake/backend/node/src/services/applicationsapi/api.ts deleted file mode 100644 index db3f7d2c7f..0000000000 --- a/twake/backend/node/src/services/applicationsapi/api.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Initializable, TwakeServiceProvider } from "../../core/platform/framework"; -import AuthServiceAPI from "../../core/platform/services/auth/provider"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../applications/api"; - -export interface ApplicationsApiServiceAPI extends TwakeServiceProvider, Initializable { - readonly platformService: PlatformServicesAPI; - readonly applicationService: ApplicationServiceAPI; - readonly authService: AuthServiceAPI; -} diff --git a/twake/backend/node/src/services/applicationsapi/index.ts b/twake/backend/node/src/services/applicationsapi/index.ts deleted file mode 100644 index 5e7d1482f4..0000000000 --- a/twake/backend/node/src/services/applicationsapi/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import web from "./web/index"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import { ApplicationsApiServiceAPI } from "./api"; -import { ApplicationServiceAPI } from "../applications/api"; -import { getService } from "./services"; -import AuthServiceAPI from "../../core/platform/services/auth/provider"; - -@Prefix("/api") -@Consumes(["platform-services", "applications"]) -export default class ApplicationsApiService extends TwakeService { - version = "1"; - name = "applicationsapi"; - service: ApplicationsApiServiceAPI; - - api(): ApplicationsApiServiceAPI { - return this.service; - } - - public async doInit(): Promise { - const platformServices = this.context.getProvider("platform-services"); - const applicationService = this.context.getProvider("applications"); - const authService = this.context.getProvider("auth"); - const fastify = platformServices.fastify.getServer(); - - this.service = getService(platformServices, applicationService, authService); - await this.service.init(); - - fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service }); - next(); - }); - - return this; - } -} diff --git a/twake/backend/node/src/services/applicationsapi/services/index.ts b/twake/backend/node/src/services/applicationsapi/services/index.ts deleted file mode 100644 index 5b6d2ee730..0000000000 --- a/twake/backend/node/src/services/applicationsapi/services/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ApplicationsApiServiceAPI } from "../api"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../../applications/api"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; - -export function getService( - platformService: PlatformServicesAPI, - applicationService: ApplicationServiceAPI, - authService: AuthServiceAPI, -) { - return new ApplicationsApiService(platformService, applicationService, authService); -} - -class ApplicationsApiService implements ApplicationsApiServiceAPI { - version: "1"; - - constructor( - readonly platformService: PlatformServicesAPI, - readonly applicationService: ApplicationServiceAPI, - readonly authService: AuthServiceAPI, - ) {} - - async init(): Promise { - return this; - } -} diff --git a/twake/backend/node/src/services/applicationsapi/web/controllers/index.ts b/twake/backend/node/src/services/applicationsapi/web/controllers/index.ts deleted file mode 100644 index 3441a5b3fc..0000000000 --- a/twake/backend/node/src/services/applicationsapi/web/controllers/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { FastifyReply, FastifyRequest, FastifyInstance, HTTPMethods } from "fastify"; -import { ApplicationsApiServiceAPI } from "../../api"; -import Application, { ApplicationObject } from "../../../applications/entities/application"; -import { - ApplicationApiExecutionContext, - ApplicationLoginRequest, - ApplicationLoginResponse, -} from "../types"; -import { ResourceGetResponse } from "../../../../utils/types"; -import { logger as log } from "../../../../core/platform/framework"; -import { - CrudExeption, - ExecutionContext, -} from "../../../../core/platform/framework/api/crud-service"; - -export class ApplicationsApiController { - constructor(readonly service: ApplicationsApiServiceAPI) {} - - async token( - request: FastifyRequest<{ Body: ApplicationLoginRequest }>, - ): Promise> { - return { - resource: { - access_token: this.service.authService.generateJWT(request.body.id, null, { - track: false, - provider_id: "", - application_id: request.body.id, - }), - }, - }; - } - - async me( - request: FastifyRequest, - reply: FastifyReply, - ): Promise> { - const context = getExecutionContext(request); - - const entity = await this.service.applicationService.applications.get({ - id: context.application_id, - }); - if (!entity) { - throw CrudExeption.notFound("Application not found"); - } - - return { resource: entity.getApplicationObject() }; - } - - async configure(request: FastifyRequest<{}>, reply: FastifyReply) { - return { error: "Not implemented (yet)" }; - } - - async closeConfigure( - request: FastifyRequest<{ Params: { configuration_id: string } }>, - reply: FastifyReply, - ) { - return { error: "Not implemented (yet)" }; - } - - async proxy(request: FastifyRequest<{}>, reply: FastifyReply, fastify: FastifyInstance) { - //TODO Check application access rights (write, read, remove for each micro services) - - //TODO save some statistics about API usage - - const route = request.url.replace("/api/", "/internal/services/"); - - fastify.inject( - { - method: request.method as HTTPMethods, - url: route, - }, - (err, response) => { - reply.headers(response.headers); - reply.send(response.payload); - }, - ); - } -} - -function getExecutionContext(request: FastifyRequest): ApplicationApiExecutionContext { - return { - application_id: request.currentUser.application_id, - user: request.currentUser, - url: request.url, - method: request.routerMethod, - transport: "http", - }; -} diff --git a/twake/backend/node/src/services/applicationsapi/web/index.ts b/twake/backend/node/src/services/applicationsapi/web/index.ts deleted file mode 100644 index 1af6c9e71e..0000000000 --- a/twake/backend/node/src/services/applicationsapi/web/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { ApplicationsApiServiceAPI } from "../api"; -import routes from "./routes"; - -export default ( - fastify: FastifyInstance, - options: FastifyRegisterOptions<{ prefix: string; service: ApplicationsApiServiceAPI }>, -): void => { - fastify.log.debug("Configuring /internal/services/applications/v1 routes"); - fastify.register(routes, options); -}; diff --git a/twake/backend/node/src/services/applicationsapi/web/routes.ts b/twake/backend/node/src/services/applicationsapi/web/routes.ts deleted file mode 100644 index 2133ffc18f..0000000000 --- a/twake/backend/node/src/services/applicationsapi/web/routes.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify"; -import { ApplicationsApiServiceAPI } from "../api"; -import { ApplicationsApiController } from "./controllers"; -import { WorkspaceUsersBaseRequest } from "../../workspaces/web/types"; -import { ApplicationApiBaseRequest } from "./types"; -import { logger as log } from "../../../core/platform/framework"; - -const routes: FastifyPluginCallback<{ service: ApplicationsApiServiceAPI }> = ( - fastify: FastifyInstance, - options, - next, -) => { - const controller = new ApplicationsApiController(options.service); - - const checkApplication = async (request: FastifyRequest<{ Body: ApplicationApiBaseRequest }>) => { - if (!request.currentUser.application_id) { - log.debug(request.currentUser); - throw fastify.httpErrors.forbidden("You should log in as application"); - } - }; - - //Authenticate the application - fastify.route({ - method: "POST", - url: "/console/v1/login", - handler: controller.token.bind(controller), - }); - - //Get myself as an application - fastify.route({ - method: "GET", - url: "/console/v1/me", - preValidation: [fastify.authenticate], - preHandler: [checkApplication], - handler: controller.me.bind(controller), - }); - - //Open a configuration popup on the client side - fastify.route({ - method: "POST", - url: "/console/v1/configure", - preValidation: [fastify.authenticate], - handler: controller.configure.bind(controller), - }); - - //Close a configuration popup on the client side - fastify.route({ - method: "DELETE", - url: "/console/v1/configure/:configuration_id", - preValidation: [fastify.authenticate], - handler: controller.closeConfigure.bind(controller), - }); - - //Get myself as an application - fastify.route({ - method: "POST", - url: "/*", //Fixme probably not working that way - preValidation: [fastify.authenticate], - handler: (request, reply) => controller.proxy.bind(controller)(request, reply, fastify), - }); - - next(); -}; - -export default routes; diff --git a/twake/backend/node/src/services/applicationsapi/web/schemas.ts b/twake/backend/node/src/services/applicationsapi/web/schemas.ts deleted file mode 100644 index 3ef6f70ae8..0000000000 --- a/twake/backend/node/src/services/applicationsapi/web/schemas.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const applicationsSchema = { - type: "object", - properties: {}, -}; diff --git a/twake/backend/node/src/services/applicationsapi/web/types.ts b/twake/backend/node/src/services/applicationsapi/web/types.ts deleted file mode 100644 index 80a893c533..0000000000 --- a/twake/backend/node/src/services/applicationsapi/web/types.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AccessToken } from "../../../utils/types"; -import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; - -export interface ApplicationApiBaseRequest { - id: string; - secret: string; -} - -export type ApplicationLoginRequest = ApplicationApiBaseRequest; - -export interface ApplicationLoginResponse { - access_token: AccessToken; -} - -export interface ApplicationApiExecutionContext extends ExecutionContext { - application_id: string; -} diff --git a/twake/backend/node/src/services/channels/entities/channel-activity.ts b/twake/backend/node/src/services/channels/entities/channel-activity.ts index 3590707468..a354c408b8 100644 --- a/twake/backend/node/src/services/channels/entities/channel-activity.ts +++ b/twake/backend/node/src/services/channels/entities/channel-activity.ts @@ -1,6 +1,7 @@ import { Type } from "class-transformer"; import { Channel } from "."; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; +import { ChannelStats } from "../services/channel/types"; import { ChannelType } from "../types"; @Entity("channel_activity", { @@ -26,10 +27,13 @@ export class ChannelActivity { @Column("last_activity", "number") last_activity: number; + @Column("stats", "encoded_json") + stats: ChannelStats; + @Column("last_message", "encoded_json") last_message: | null - | {} + | Record | { date: number; sender: string; diff --git a/twake/backend/node/src/services/channels/entities/channel-counters.ts b/twake/backend/node/src/services/channels/entities/channel-counters.ts new file mode 100644 index 0000000000..3958848f1a --- /dev/null +++ b/twake/backend/node/src/services/channels/entities/channel-counters.ts @@ -0,0 +1,35 @@ +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; + +export const TYPE = "channel_counters"; + +@Entity(TYPE, { + primaryKey: [["id"], "counter_type", "company_id", "workspace_id"], + type: TYPE, +}) +export class ChannelCounterEntity { + @Column("id", "uuid") + id: string; + + @Column("counter_type", "string") + counter_type: string; + + @Column("company_id", "uuid") + company_id: string; + + @Column("workspace_id", "string") + workspace_id: string; + + @Column("value", "counter") + value: number; +} + +export type ChannelCounterPrimaryKey = Pick< + ChannelCounterEntity, + "id" | "counter_type" | "company_id" | "workspace_id" +>; + +export enum ChannelUserCounterType { + MEMBERS = "members", + MESSAGES = "messages", + GUESTS = "guests", +} diff --git a/twake/backend/node/src/services/channels/entities/channel-member-read-cursors.ts b/twake/backend/node/src/services/channels/entities/channel-member-read-cursors.ts new file mode 100644 index 0000000000..1054ad4b96 --- /dev/null +++ b/twake/backend/node/src/services/channels/entities/channel-member-read-cursors.ts @@ -0,0 +1,34 @@ +import { Type } from "class-transformer"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; + +@Entity("channel_member_read_cursors", { + primaryKey: [["company_id"], "channel_id", "user_id"], + type: "channel_member_read_cursors", +}) +export class ChannelMemberReadCursors { + /** + * Primary key + */ + @Type(() => String) + @Column("company_id", "uuid", { generator: "uuid" }) + company_id: string; + + /** + * Primary key + */ + @Type(() => String) + @Column("user_id", "uuid") + user_id: string; + + /** + * Primary key + */ + @Type(() => String) + @Column("channel_id", "uuid") + channel_id: string; + + @Column("read_section", "encoded_json") + read_section: ReadSection; +} + +export type ReadSection = [string, string]; diff --git a/twake/backend/node/src/services/channels/entities/channel-member.ts b/twake/backend/node/src/services/channels/entities/channel-member.ts index cba728d2af..77089489b0 100644 --- a/twake/backend/node/src/services/channels/entities/channel-member.ts +++ b/twake/backend/node/src/services/channels/entities/channel-member.ts @@ -1,7 +1,8 @@ import { Type } from "class-transformer"; import { merge } from "lodash"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; import { ChannelMemberNotificationLevel, ChannelMemberType } from "../types"; +import { UserObject } from "../../../services/user/web/types"; /** * Defines the member <-> channel link and member settings in channel @@ -67,7 +68,7 @@ export class ChannelMember { * Defaults to all */ @Column("notification_level", "string") - notification_level: ChannelMemberNotificationLevel = ChannelMemberNotificationLevel.MENTIONS; + notification_level: ChannelMemberNotificationLevel = ChannelMemberNotificationLevel.ALL; /** * Member expiration in channel (only for guests) @@ -98,6 +99,8 @@ export function getChannelMemberInstance(member: Partial): Channe return merge(new ChannelMember(), member); } +export type ChannelMemberWithUser = ChannelMember & { user: UserObject }; + /** * The channel_members table allows to get all the members of a channel. * Table name is `channel_members` diff --git a/twake/backend/node/src/services/channels/entities/channel-pending-emails.ts b/twake/backend/node/src/services/channels/entities/channel-pending-emails.ts index c756d455f7..0baa61979a 100644 --- a/twake/backend/node/src/services/channels/entities/channel-pending-emails.ts +++ b/twake/backend/node/src/services/channels/entities/channel-pending-emails.ts @@ -1,7 +1,6 @@ import { Type } from "class-transformer"; import { merge } from "lodash"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; -import { ChannelMemberType } from "../types"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; @Entity("channel_pending_emails", { primaryKey: [["company_id", "workspace_id"], "channel_id", "email"], diff --git a/twake/backend/node/src/services/channels/entities/channel.search.ts b/twake/backend/node/src/services/channels/entities/channel.search.ts new file mode 100644 index 0000000000..78a7d5bee8 --- /dev/null +++ b/twake/backend/node/src/services/channels/entities/channel.search.ts @@ -0,0 +1,24 @@ +import { Channel } from "./channel"; + +export default { + index: "channels", + source: (entity: Channel) => { + return { + workspace_id: entity.workspace_id, + company_id: entity.company_id, + name: entity.channel_group + " " + entity.name, + }; + }, + mongoMapping: { + text: { + name: "text", + }, + }, + esMapping: { + properties: { + name: { type: "text", index_prefixes: { min_chars: 1 } }, + workspace_id: { type: "keyword" }, + company_id: { type: "keyword" }, + }, + }, +}; diff --git a/twake/backend/node/src/services/channels/entities/channel.ts b/twake/backend/node/src/services/channels/entities/channel.ts index e3ec18e7d1..4924f45030 100644 --- a/twake/backend/node/src/services/channels/entities/channel.ts +++ b/twake/backend/node/src/services/channels/entities/channel.ts @@ -1,13 +1,16 @@ import { Type } from "class-transformer"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; -import { ChannelVisibility, ChannelType } from "../types"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; +import { ChannelType, ChannelVisibility } from "../types"; import { ChannelMember } from "./channel-member"; import { UserObject } from "../../user/web/types"; import { merge } from "lodash"; +import search from "./channel.search"; +import { ChannelActivity } from "./channel-activity"; @Entity("channels", { primaryKey: [["company_id", "workspace_id"], "id"], type: "channels", + search, }) export class Channel { // uuid-v4 @@ -20,7 +23,7 @@ export class Channel { workspace_id: string | ChannelType.DIRECT; @Type(() => String) - @Column("id", "timeuuid", { generator: "timeuuid" }) + @Column("id", "uuid", { generator: "uuid" }) id: string; @Column("name", "encoded_string") @@ -52,6 +55,7 @@ export class Channel { @Type(() => String) owner: string; + //This is only used for direct channels @Column("members", "encoded_json") members: string[] = []; @@ -86,6 +90,8 @@ export class Channel { export class UserChannel extends Channel { user_member: ChannelMember; + last_activity: ChannelActivity["last_activity"]; + last_message: ChannelActivity["last_message"]; } export class UsersIncludedChannel extends Channel { @@ -95,3 +101,5 @@ export class UsersIncludedChannel extends Channel { export function getInstance(channel: Partial): Channel { return merge(new Channel(), channel); } + +export type ChannelPrimaryKey = Pick; diff --git a/twake/backend/node/src/services/channels/entities/channel_counters.ts b/twake/backend/node/src/services/channels/entities/channel_counters.ts deleted file mode 100644 index 989a24782c..0000000000 --- a/twake/backend/node/src/services/channels/entities/channel_counters.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; - -export const TYPE = "channel_counters"; - -@Entity(TYPE, { - primaryKey: [["id"], "counter_type", "company_id", "workspace_id"], - type: TYPE, -}) -export class ChannelCounterEntity { - @Column("id", "uuid") - id: string; - - @Column("counter_type", "string") - counter_type: string; - - @Column("company_id", "uuid") - company_id: string; - - @Column("workspace_id", "string") - workspace_id: string; - - @Column("value", "counter") - value: number; -} - -export type ChannelCounterPrimaryKey = Pick< - ChannelCounterEntity, - "id" | "counter_type" | "company_id" | "workspace_id" ->; - -export enum ChannelUserCounterType { - MEMBERS = "members", - GUESTS = "guests", -} diff --git a/twake/backend/node/src/services/channels/entities/default-channel.ts b/twake/backend/node/src/services/channels/entities/default-channel.ts index 754a7b7ca1..64c7f60adb 100644 --- a/twake/backend/node/src/services/channels/entities/default-channel.ts +++ b/twake/backend/node/src/services/channels/entities/default-channel.ts @@ -1,6 +1,6 @@ import { Type } from "class-transformer"; import { merge } from "lodash"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; import { ChannelType } from "../types"; @Entity("default_channels", { diff --git a/twake/backend/node/src/services/channels/entities/direct-channel.ts b/twake/backend/node/src/services/channels/entities/direct-channel.ts index a39ee23406..1dd92a3508 100644 --- a/twake/backend/node/src/services/channels/entities/direct-channel.ts +++ b/twake/backend/node/src/services/channels/entities/direct-channel.ts @@ -1,6 +1,6 @@ import { Type } from "class-transformer"; import { merge } from "lodash"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; /** * Direct Channel information. diff --git a/twake/backend/node/src/services/channels/entities/index.ts b/twake/backend/node/src/services/channels/entities/index.ts index d3321e07ef..41979e7909 100644 --- a/twake/backend/node/src/services/channels/entities/index.ts +++ b/twake/backend/node/src/services/channels/entities/index.ts @@ -2,6 +2,7 @@ export * from "./channel"; export * from "./member"; export * from "./tab"; export * from "./channel-member"; +export * from "./channel-member-read-cursors"; export { ChannelPendingEmails, ChannelPendingEmailsPrimaryKey, diff --git a/twake/backend/node/src/services/channels/entities/tab.ts b/twake/backend/node/src/services/channels/entities/tab.ts index f4fd0c8d22..01ce1b8cca 100644 --- a/twake/backend/node/src/services/channels/entities/tab.ts +++ b/twake/backend/node/src/services/channels/entities/tab.ts @@ -1,5 +1,5 @@ import { Type } from "class-transformer"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; import { ChannelType } from "../types"; @Entity("channel_tabs", { diff --git a/twake/backend/node/src/services/channels/index.ts b/twake/backend/node/src/services/channels/index.ts index 4ee5205035..1aec35f873 100644 --- a/twake/backend/node/src/services/channels/index.ts +++ b/twake/backend/node/src/services/channels/index.ts @@ -1,36 +1,23 @@ -import { Consumes, Prefix, TwakeService } from "../../core/platform/framework"; -import ChannelServiceAPI from "./provider"; -import { getService } from "./services"; -import web from "./web/index"; -import UserServiceAPI from "../user/api"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; +import { Prefix, TwakeService } from "../../core/platform/framework"; +import WebServerAPI from "../../core/platform/services/webserver/provider"; +import web from "./web"; @Prefix("/internal/services/channels/v1") -@Consumes(["platform-services", "webserver", "database", "pubsub", "user", "realtime"]) -export default class ChannelService extends TwakeService { +export default class ChannelService extends TwakeService { version = "1"; name = "channels"; - service: ChannelServiceAPI; - - api(): ChannelServiceAPI { - return this.service; - } public async doInit(): Promise { - const platformServices = this.context.getProvider("platform-services"); - const fastify = platformServices.fastify.getServer(); - const user = this.context.getProvider("user"); - const realtime = this.context.getProvider("realtime"); - - this.service = getService(platformServices, user); - this.service.init && (await this.service.init()); - + const fastify = this.context.getProvider("webserver").getServer(); fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + web(instance, { prefix: this.prefix }); next(); }); - return this; } + + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/channels/provider.ts b/twake/backend/node/src/services/channels/provider.ts deleted file mode 100644 index 771ea85848..0000000000 --- a/twake/backend/node/src/services/channels/provider.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { - CRUDService, - ListResult, - Paginable, - Pagination, - UpdateResult, -} from "../../core/platform/framework/api/crud-service"; -import { Initializable, TwakeServiceProvider } from "../../core/platform/framework/api"; -import { - Channel, - ChannelMember, - ChannelMemberPrimaryKey, - ChannelPendingEmails, - ChannelPendingEmailsPrimaryKey, - ChannelTab, - ChannelTabPrimaryKey, - DefaultChannel, - DefaultChannelPrimaryKey, - UsersIncludedChannel, -} from "./entities"; -import { ChannelExecutionContext, WorkspaceExecutionContext } from "./types"; -import { User } from "../../utils/types"; -import { DirectChannel } from "./entities/direct-channel"; -import { ChannelActivity } from "./entities/channel-activity"; -import { Observable } from "rxjs"; -import { ChannelPendingEmailsListQueryParameters } from "./web/types"; -import { NewUserInWorkspaceNotification } from "./services/channel/types"; -import { ChannelCounterPrimaryKey, ChannelUserCounterType } from "./entities/channel_counters"; - -export type ChannelPrimaryKey = { - id?: string; - company_id?: string; - workspace_id?: string; -}; - -export type ChannelActivityMessage = { - date: number; - sender: string; - sender_name: string; - title: string; - text: string; -}; - -export interface ChannelService - extends TwakeServiceProvider, - Initializable, - CRUDService { - /** - * Create direct channel - * - * @param directChannel - */ - createDirectChannel(directChannel: DirectChannel): Promise; - - /** - * Get all the direct channels for a user - * TODO: Return a list of Channel with a list of users - * @param user - */ - getDirectChannel(directChannel: DirectChannel): Promise; - - /** - * Get a direct channel in company for given company id and set of users - */ - getDirectChannelInCompany(companyId: string, users: string[]): Promise; - - /** - * Get direct channels in company for given company id - */ - getDirectChannelsInCompany( - pagination: Pagination, - company_id: string, - ): Promise>; - - /** - * Get all the direct channels in a company for the given user - * - * @param companyId - * @param userId - */ - getDirectChannelsForUsersInCompany(companyId: string, userId: string): Promise; - - /** - * Mark the channel as read for the given user - * - * @param channel - * @param user - */ - markAsRead( - channel: ChannelPrimaryKey, - user: User, - context: WorkspaceExecutionContext, - ): Promise; - - /** - * Mark the channel as unread - * - * @param channel - * @param user - * @param context - */ - markAsUnread( - channel: ChannelPrimaryKey, - user: User, - context: WorkspaceExecutionContext, - ): Promise; - - /** - * Update the last activity for the given channel - * - * @param channel The channel to update the last_activity - */ - updateLastActivity( - payload: { - date: number; - channel: ChannelPrimaryKey; - message: ChannelActivityMessage; - }, - context: WorkspaceExecutionContext, - ): Promise>; - - /** - * Get the list of all default channels for the given workspace. - * - * @param workspace - */ - getDefaultChannels( - workspace: Required>, - pagination?: Paginable, - ): Promise; - - /** - * Add user to the default channels of the given workspace - * - * @param userId - * @param workspace - * @return a list of ChannelMember objects representing where the user has been added. - * The list will not contain the ChannelMember of the user is already a member. - */ - addUserToDefaultChannels( - user: User, - workspace: Required>, - ): Promise; - - /** - * Include users to channel itself, also generate the channel name - * @param channel - * @param context - */ - includeUsersInDirectChannel( - channel: Channel, - context?: WorkspaceExecutionContext, - ): Promise; -} -export interface MemberService - extends TwakeServiceProvider, - Initializable, - CRUDService { - listUserChannels( - user: User, - pagination: Pagination, - context: WorkspaceExecutionContext, - ): Promise>; - - /** - * Check if user is channel member - */ - isChannelMember(user: User, channel: Channel): Promise; - - /** - * Add a list of users to channel. - * Should never rejects: If the user is not added, it will not be in the result.member object - * - * @param users Users to add - * @param channel Channel to add users to - */ - addUsersToChannel( - users: Pick[], - channel: ChannelPrimaryKey, - ): Promise>; - - /** - * Add the user to a list of channels. - * Should never rejects: If the user is not added, it will not be in the result.member object - * - * @param user the user to add - * @param channels the channels to add the user to - */ - addUserToChannels( - user: Pick, - channels: ChannelPrimaryKey[], - ): Promise>; - - getUsersCount(counterPk: ChannelCounterPrimaryKey): Promise; -} - -export interface TabService - extends TwakeServiceProvider, - Initializable, - CRUDService {} - -export default interface ChannelServiceAPI extends TwakeServiceProvider, Initializable { - channels: ChannelService; - pendingEmails: ChannelPendingEmailService; - members: MemberService; - tabs: TabService; -} - -/** - * Manage default channels entities - */ -export interface DefaultChannelService - extends TwakeServiceProvider, - Initializable, - CRUDService { - /** - * Get all the default channels in the given workspace - * - * @param workspace the workspace to get default channels from - */ - getDefaultChannels( - workspace: Pick, - ): Promise; - - /** - * Get a stream of default channels - * @param workspace - */ - getDefaultChannels$( - workspace: Pick, - pagination?: Paginable, - ): Observable; - - /** - * Add given user to all default channels of the given workspace. - * If the user is already member of the default channel, it will not be added. - * - * @param userId - * @param workspace - */ - addUserToDefaultChannels( - user: User, - workspace: Required>, - ): Promise>; -} - -export interface ChannelPendingEmailService - extends TwakeServiceProvider, - Initializable, - CRUDService { - findPendingEmails( - pk: ChannelPendingEmailsListQueryParameters, - ): Promise>; - - proccessPendingEmails( - user: NewUserInWorkspaceNotification, - workspace: Required>, - ): Promise; -} diff --git a/twake/backend/node/src/services/channels/services/channel/activities/index.ts b/twake/backend/node/src/services/channels/services/channel/activities/index.ts deleted file mode 100644 index 399e14e103..0000000000 --- a/twake/backend/node/src/services/channels/services/channel/activities/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { PubsubServiceAPI } from "../../../../../core/platform/services/pubsub/api"; -import Activities from "./service"; - -export const getService = (pubsub: PubsubServiceAPI): Activities => new Activities(pubsub); diff --git a/twake/backend/node/src/services/channels/services/channel/activities/service.ts b/twake/backend/node/src/services/channels/services/channel/activities/service.ts index f90c040f43..0314e3afaa 100644 --- a/twake/backend/node/src/services/channels/services/channel/activities/service.ts +++ b/twake/backend/node/src/services/channels/services/channel/activities/service.ts @@ -1,20 +1,16 @@ import { getLogger, Initializable } from "../../../../../core/platform/framework"; -import { localEventBus } from "../../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../../core/platform/framework/event-bus"; import { Channel as ChannelEntity, ChannelMember } from "../../../entities/"; import { ResourceEventsPayload } from "../../../../../utils/types"; import { ActivityObjectType, ActivityPublishedType } from "./types"; import _, { sortBy } from "lodash"; -import { PubsubServiceAPI } from "../../../../../core/platform/services/pubsub/api"; +import { MessageQueueServiceAPI } from "../../../../../core/platform/services/message-queue/api"; import { ChannelParameters } from "../../../web/types"; import { ChannelVisibility } from "../../../types"; const logger = getLogger("channel.activities"); export default class Activities implements Initializable { - pubsub: PubsubServiceAPI; - - constructor(pubsub: PubsubServiceAPI) { - this.pubsub = pubsub; - } + messageQueue: MessageQueueServiceAPI; async init(): Promise { const channelConnectorCreatedEvent = "channel:connector:created"; @@ -212,7 +208,7 @@ export default class Activities implements Initializable { ): Promise { logger.debug(`Activities - New ${event} event %o`, data); try { - await this.pubsub.publish("channel:activity_message", { + await this.messageQueue.publish("channel:activity_message", { data: { channel_id: channel.id, workspace_id: channel.workspace_id, diff --git a/twake/backend/node/src/services/channels/services/channel/default/listener.ts b/twake/backend/node/src/services/channels/services/channel/default/listener.ts index 48db15f0b1..9f599e1b61 100644 --- a/twake/backend/node/src/services/channels/services/channel/default/listener.ts +++ b/twake/backend/node/src/services/channels/services/channel/default/listener.ts @@ -1,13 +1,13 @@ import { Channel, getDefaultChannelInstance } from "../../../entities"; -import { Initializable, getLogger } from "../../../../../core/platform/framework"; -import { localEventBus } from "../../../../../core/platform/framework/pubsub"; +import { getLogger, Initializable } from "../../../../../core/platform/framework"; +import { localEventBus } from "../../../../../core/platform/framework/event-bus"; import { ResourceEventsPayload } from "../../../../../utils/types"; -import { DefaultChannelService } from "../../../provider"; +import DefaultChannelServiceImpl from "./service"; const logger = getLogger("channel:default:listener"); export default class DefaultChannelListener implements Initializable { - constructor(private service: DefaultChannelService) {} + constructor(private service: DefaultChannelServiceImpl) {} async init(): Promise { localEventBus.subscribe( @@ -68,6 +68,7 @@ export default class DefaultChannelListener implements Initializable { company_id: event.channel.company_id, workspace_id: event.channel.workspace_id, }), + undefined, ) .catch((err: Error) => { logger.error({ err }, "Default channel %id can not be updated", event.channel.id); @@ -103,6 +104,7 @@ export default class DefaultChannelListener implements Initializable { company_id: event.channel.company_id, workspace_id: event.channel.workspace_id, }), + undefined, ) .catch((err: Error) => { logger.warn({ err }, "Default channel %id can not be created", event.channel.id); diff --git a/twake/backend/node/src/services/channels/services/channel/default/service.ts b/twake/backend/node/src/services/channels/services/channel/default/service.ts index 5b179f930c..64a65684d5 100644 --- a/twake/backend/node/src/services/channels/services/channel/default/service.ts +++ b/twake/backend/node/src/services/channels/services/channel/default/service.ts @@ -1,50 +1,49 @@ -import { from, Observable, concat, EMPTY } from "rxjs"; +import { concat, EMPTY, from, Observable } from "rxjs"; import { filter, mergeMap, toArray } from "rxjs/operators"; -import { DatabaseServiceAPI } from "../../../../../core/platform/services/database/api"; import Repository from "../../../../../core/platform/services/database/services/orm/repository/repository"; -import { DefaultChannel, DefaultChannelPrimaryKey } from "../../../entities/default-channel"; -import ChannelServiceAPI, { DefaultChannelService } from "../../../provider"; +import { + Channel, + ChannelMember, + DefaultChannel, + DefaultChannelPrimaryKey, +} from "../../../entities"; import { CreateResult, - UpdateResult, - SaveResult, + CrudException, DeleteResult, - Paginable, + ExecutionContext, ListResult, - CrudExeption, + Paginable, + SaveResult, + UpdateResult, } from "../../../../../core/platform/framework/api/crud-service"; import { ChannelExecutionContext } from "../../../types"; import DefaultChannelListener from "./listener"; import { getLogger } from "../../../../../core/platform/framework"; -import UserServiceAPI from "../../../../user/api"; -import { ChannelMember } from "../../../../channels/entities/channel-member"; import { User } from "../../../../../utils/types"; -import { Channel } from "../../../../../services/channels/entities"; import WorkspaceUser from "../../../../workspaces/entities/workspace_user"; +import gr from "../../../../global-resolver"; const logger = getLogger("channel.default"); -export default class DefaultChannelServiceImpl implements DefaultChannelService { +export default class DefaultChannelServiceImpl { version: "1"; repository: Repository; listener: DefaultChannelListener; - constructor( - private database: DatabaseServiceAPI, - private channelService: ChannelServiceAPI, - private userService: UserServiceAPI, - ) {} - async init(): Promise { - this.repository = await this.database.getRepository("default_channels", DefaultChannel); + this.repository = await gr.database.getRepository("default_channels", DefaultChannel); this.listener = new DefaultChannelListener(this); await this.listener.init(); return this; } - async create(channel: DefaultChannel): Promise> { - await this.repository.save(channel); + async create( + channel: DefaultChannel, + context: ExecutionContext, + ): Promise> { + await this.repository.save(channel, context); // Once a default channel has been successfully created, we have to add all the workspace users as member of the channel // There are several ways to do it: Directly or using pubsub @@ -54,8 +53,8 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService return new CreateResult("default_channel", channel); } - get(pk: DefaultChannelPrimaryKey): Promise { - return this.repository.findOne(pk); + get(pk: DefaultChannelPrimaryKey, context: ExecutionContext): Promise { + return this.repository.findOne(pk, {}, context); } update( @@ -80,14 +79,17 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService throw new Error("Method not implemented."); } - async delete(pk: DefaultChannelPrimaryKey): Promise> { - const defaultChannel = await this.get(pk); + async delete( + pk: DefaultChannelPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const defaultChannel = await this.get(pk, context); if (!defaultChannel) { - throw CrudExeption.notFound("Default channel has not been found"); + throw CrudException.notFound("Default channel has not been found"); } - await this.repository.remove(defaultChannel); + await this.repository.remove(defaultChannel, context); return new DeleteResult("default_channel", defaultChannel, true); } @@ -136,7 +138,7 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService addWorkspaceUsersToChannel( channel: DefaultChannelPrimaryKey, ): Observable<{ user?: WorkspaceUser; member?: ChannelMember; added: boolean; err?: Error }> { - const workspaceUsers$ = this.userService.workspaces.getAllUsers$({ + const workspaceUsers$ = gr.services.workspaces.getAllUsers$({ workspaceId: channel.workspace_id, }); @@ -145,13 +147,13 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService filter(wsUser => !wsUser.isExternal), mergeMap(wsUser => from( - this.channelService.members + gr.services.channels.members .addUserToChannels({ id: wsUser.userId }, [ { company_id: channel.company_id, workspace_id: channel.workspace_id, id: channel.channel_id, - }, + } as Channel, ]) .then(result => ({ user: wsUser, @@ -176,7 +178,7 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService } try { - const companyUser = await this.userService.companies.getCompanyUser( + const companyUser = await gr.services.companies.getCompanyUser( { id: workspace.company_id }, user, ); @@ -207,7 +209,11 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService logger.info("Adding user %s to channels %s", user, JSON.stringify(channels)); - return (await this.channelService.members.addUserToChannels(user, channels)).getEntities(); + const regChannels = channels.map(c => ({ id: c.channel_id, ...c } as any as Channel)); + + return ( + await gr.services.channels.members.addUserToChannels(user, regChannels) + ).getEntities(); } catch (err) { logger.error({ err }, "Error while adding user for default channels"); throw new Error("Error while adding user for default channels"); @@ -217,21 +223,27 @@ export default class DefaultChannelServiceImpl implements DefaultChannelService getDefaultChannels( workspace: Pick, pagination?: Paginable, + context?: ExecutionContext, ): Promise { - return this.getDefaultChannels$(workspace, pagination).pipe(toArray()).toPromise(); + return this.getDefaultChannels$(workspace, pagination, context).pipe(toArray()).toPromise(); } getDefaultChannels$( workspace: Pick, pagination?: Paginable, + context?: ExecutionContext, ): Observable { const list = ( workspace: Pick, pagination: Paginable, ) => { - return this.repository.find(workspace, { - pagination: { limitStr: pagination?.limitStr, page_token: pagination?.page_token }, - }); + return this.repository.find( + workspace, + { + pagination: { limitStr: pagination?.limitStr, page_token: pagination?.page_token }, + }, + context, + ); }; return from(list(workspace, pagination)).pipe( diff --git a/twake/backend/node/src/services/channels/services/channel/index.ts b/twake/backend/node/src/services/channels/services/channel/index.ts deleted file mode 100644 index 08cd05c413..0000000000 --- a/twake/backend/node/src/services/channels/services/channel/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import UserServiceAPI from "../../../user/api"; -import ChannelServiceAPI, { ChannelService } from "../../provider"; -import { Service } from "./service"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - channelService: ChannelServiceAPI, - userService: UserServiceAPI, -): ChannelService { - return new Service(platformServices, channelService, userService); -} diff --git a/twake/backend/node/src/services/channels/services/channel/pending-emails/service.ts b/twake/backend/node/src/services/channels/services/channel/pending-emails/service.ts index 267c148f03..d3959550f8 100644 --- a/twake/backend/node/src/services/channels/services/channel/pending-emails/service.ts +++ b/twake/backend/node/src/services/channels/services/channel/pending-emails/service.ts @@ -1,45 +1,36 @@ -import { DatabaseServiceAPI } from "../../../../../core/platform/services/database/api"; import Repository from "../../../../../core/platform/services/database/services/orm/repository/repository"; -import ChannelServiceAPI, { - ChannelPendingEmailService, - ChannelPrimaryKey, -} from "../../../provider"; import { CreateResult, - UpdateResult, - SaveResult, + CrudException, DeleteResult, + ExecutionContext, ListResult, - CrudExeption, Pagination, + SaveResult, + UpdateResult, } from "../../../../../core/platform/framework/api/crud-service"; import { ChannelExecutionContext } from "../../../types"; import { getLogger } from "../../../../../core/platform/framework"; import { - ChannelPendingEmailsPrimaryKey, + Channel, ChannelPendingEmails, + ChannelPendingEmailsPrimaryKey, + ChannelPrimaryKey, getChannelPendingEmailsInstance, } from "../../../entities"; import { ChannelPendingEmailsListQueryParameters } from "../../../web/types"; import { plainToClass } from "class-transformer"; -import UserServiceAPI from "../../../../user/api"; import { NewUserInWorkspaceNotification } from "../types"; - +import gr from "../../../../global-resolver"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const logger = getLogger("channel.pending_emails"); -export default class ChannelPendingEmailsService implements ChannelPendingEmailService { +export default class ChannelPendingEmailServiceImpl { version: "1"; repository: Repository; - constructor( - private database: DatabaseServiceAPI, - private userService: UserServiceAPI, - private service: ChannelServiceAPI, - ) {} - async init(): Promise { - this.repository = await this.database.getRepository( + this.repository = await gr.database.getRepository( "channel_pending_emails", ChannelPendingEmails, ); @@ -47,16 +38,22 @@ export default class ChannelPendingEmailsService implements ChannelPendingEmailS return this; } - async create(pendingEmail: ChannelPendingEmails): Promise> { - await this.repository.save(pendingEmail); + async create( + pendingEmail: ChannelPendingEmails, + context: ExecutionContext, + ): Promise> { + await this.repository.save(pendingEmail, context); // Once a channel pending email has been successfully created, we have to add him to all channels of the company that he was invited //this.onCreated(pendingEmail); return new CreateResult("channel_pending_emails", pendingEmail); } - get(pk: ChannelPendingEmailsPrimaryKey): Promise { - return this.repository.findOne(pk); + get( + pk: ChannelPendingEmailsPrimaryKey, + context: ExecutionContext, + ): Promise { + return this.repository.findOne(pk, {}, context); } update( @@ -81,14 +78,17 @@ export default class ChannelPendingEmailsService implements ChannelPendingEmailS throw new Error("Method not implemented."); } - async delete(pk: ChannelPendingEmailsPrimaryKey): Promise> { - const pendingEmail = await this.get(pk); + async delete( + pk: ChannelPendingEmailsPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const pendingEmail = await this.get(pk, context); if (!pendingEmail) { - throw CrudExeption.notFound("Channel pendingEmail has not been found"); + throw CrudException.notFound("Channel pendingEmail has not been found"); } - await this.repository.remove(pendingEmail); + await this.repository.remove(pendingEmail, context); return new DeleteResult("channel_pending_emails", pendingEmail, true); } @@ -107,7 +107,7 @@ export default class ChannelPendingEmailsService implements ChannelPendingEmailS channel_id: context.channel.id, }; - const result = await this.repository.find(pk, { pagination }); + const result = await this.repository.find(pk, { pagination }, context); return new ListResult( "channel_pending_emails", @@ -122,21 +122,23 @@ export default class ChannelPendingEmailsService implements ChannelPendingEmailS findPendingEmails( pk: ChannelPendingEmailsListQueryParameters, + context: ExecutionContext, ): Promise> { - return this.repository.find(pk); + return this.repository.find(pk, {}, context); } async proccessPendingEmails( user: NewUserInWorkspaceNotification, workspace: Required>, + context: ExecutionContext, ): Promise { // Get user object - const userObj = await this.userService.users.get({ + const userObj = await gr.services.users.get({ id: user.user_id, }); // All pending emails in workspace - const allPendingEmailsInWorkspace = await this.repository.find(workspace); + const allPendingEmailsInWorkspace = await this.repository.find(workspace, {}, context); // Filter pending emails in workspace with user object email allPendingEmailsInWorkspace.filterEntities(({ email }) => email === userObj.email_canonical); @@ -146,12 +148,12 @@ export default class ChannelPendingEmailsService implements ChannelPendingEmailS .getEntities() .forEach(async ({ workspace_id, channel_id, company_id, email }) => { // Add user to channel - const list = await this.service.members.addUserToChannels(userObj, [ + const list = await gr.services.channels.members.addUserToChannels(userObj, [ { workspace_id, company_id, id: channel_id, - }, + } as Channel, ]); // If added to channel, delete pending email diff --git a/twake/backend/node/src/services/channels/services/channel/realtime.ts b/twake/backend/node/src/services/channels/services/channel/realtime.ts index 82d91fa503..745ebdd35b 100644 --- a/twake/backend/node/src/services/channels/services/channel/realtime.ts +++ b/twake/backend/node/src/services/channels/services/channel/realtime.ts @@ -1,4 +1,4 @@ -import { User, Workspace, WebsocketMetadata } from "../../../../utils/types"; +import { User, WebsocketMetadata, Workspace } from "../../../../utils/types"; import { Channel } from "../../entities"; import { WorkspaceExecutionContext } from "../../types"; import { isDirectChannel } from "../../utils"; diff --git a/twake/backend/node/src/services/channels/services/channel/service.ts b/twake/backend/node/src/services/channels/services/channel/service.ts index d0465ceb87..0faefcdb4f 100644 --- a/twake/backend/node/src/services/channels/services/channel/service.ts +++ b/twake/backend/node/src/services/channels/services/channel/service.ts @@ -7,24 +7,20 @@ import { RealtimeUpdated, } from "../../../../core/platform/framework"; import { - CrudExeption, + CrudException, DeleteResult, + ExecutionContext, ListResult, OperationType, Pagination, SaveResult, UpdateResult, } from "../../../../core/platform/framework/api/crud-service"; -import ChannelServiceAPI, { - ChannelActivityMessage, - ChannelPrimaryKey, - ChannelService, - DefaultChannelService, -} from "../../provider"; -import { ChannelObject } from "./types"; +import { ChannelActivityMessage, ChannelObject, SearchChannelOptions } from "./types"; import { Channel, ChannelMember, + ChannelPrimaryKey, DefaultChannel, UserChannel, UsersIncludedChannel, @@ -45,47 +41,35 @@ import Repository, { FindFilter, } from "../../../../core/platform/services/database/services/orm/repository/repository"; import { ChannelActivity } from "../../entities/channel-activity"; -import { - PubsubParameter, - PubsubPublish, -} from "../../../../core/platform/services/pubsub/decorators/publish"; -import { localEventBus } from "../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; import DefaultChannelServiceImpl from "./default/service"; -import UserServiceAPI from "../../../user/api"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; +import { formatUser } from "../../../../utils/users"; +import gr from "../../../global-resolver"; +import { + KnowledgeGraphEvents, + KnowledgeGraphGenericEventPayload, +} from "../../../../core/platform/services/knowledge-graph/types"; +import { ChannelUserCounterType } from "../../entities/channel-counters"; const logger = getLogger("channel.service"); -export class Service implements ChannelService { +export class ChannelServiceImpl { version: "1"; activityRepository: Repository; channelRepository: Repository; directChannelRepository: Repository; - defaultChannelService: DefaultChannelService; - - constructor( - private platformServices: PlatformServicesAPI, - private channelService: ChannelServiceAPI, - private userService: UserServiceAPI, - ) {} + defaultChannelService: DefaultChannelServiceImpl; async init(): Promise { - this.defaultChannelService = new DefaultChannelServiceImpl( - this.platformServices.database, - this.channelService, - this.userService, - ); + this.defaultChannelService = new DefaultChannelServiceImpl(); try { - this.activityRepository = await this.platformServices.database.getRepository( + this.activityRepository = await gr.database.getRepository( "channel_activity", ChannelActivity, ); - this.channelRepository = await this.platformServices.database.getRepository( - "channels", - Channel, - ); - this.directChannelRepository = await this.platformServices.database.getRepository( + this.channelRepository = await gr.database.getRepository("channels", Channel); + this.directChannelRepository = await gr.database.getRepository( "direct_channels", DirectChannel, ); @@ -99,6 +83,15 @@ export class Service implements ChannelService { logger.warn("Can not initialize default channel service", err); } + localEventBus.subscribe("workspace:user:deleted", async data => { + if (data?.user?.id && data?.company?.id) + gr.services.channels.members.ensureUserNotInWorkspaceIsNotInChannel( + data.user, + data.workspace, + undefined, + ); + }); + return this; } @@ -118,8 +111,7 @@ export class Service implements ChannelService { const mode = channel.id ? OperationType.UPDATE : OperationType.CREATE; const isDirectChannel = Channel.isDirectChannel(channel); const isWorkspaceAdmin = - !isDirectChannel && - (await userIsWorkspaceAdmin(this.userService, context.user, context.workspace)); + !isDirectChannel && (await userIsWorkspaceAdmin(context.user, context.workspace)); const isPrivateChannel = Channel.isPrivateChannel(channel); const isDefaultChannel = Channel.isDefaultChannel(channel); @@ -133,10 +125,10 @@ export class Service implements ChannelService { if (mode === OperationType.UPDATE) { logger.debug("Updating channel"); - channelToUpdate = await this.get(this.getPrimaryKey(channel)); + channelToUpdate = await this.get(this.getPrimaryKey(channel), context); if (!channelToUpdate) { - throw CrudExeption.notFound("Channel not found"); + throw CrudException.notFound("Channel not found"); } const isChannelOwner = this.isChannelOwner(channelToUpdate, context.user); @@ -156,20 +148,22 @@ export class Service implements ChannelService { const fields = Object.keys(channelDiff) as Array>; if (!fields.length) { - throw CrudExeption.badRequest("Nothing to update"); + throw CrudException.badRequest("Nothing to update"); } const updatableFields = fields.filter(field => updatableParameters[field]); if (!updatableFields.length) { - throw CrudExeption.badRequest("Current user can not update requested fields"); + throw CrudException.badRequest("Current user can not update requested fields"); } channelToSave = cloneDeep(channelToUpdate); updatableFields.forEach(field => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (channelToSave as any)[field] = channel[field]; + if (channel[field] !== undefined) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (channelToSave as any)[field] = channel[field]; + } }); localEventBus.publish("channel:updated", { @@ -183,7 +177,7 @@ export class Service implements ChannelService { if (mode === OperationType.CREATE) { if (isPrivateChannel && isDefaultChannel) { - throw CrudExeption.badRequest("Private channel can not be default"); + throw CrudException.badRequest("Private channel can not be default"); } if (isDirectChannel) { @@ -192,23 +186,28 @@ export class Service implements ChannelService { logger.info("Direct channel creation with members %o", options.members); if (context.workspace.workspace_id !== ChannelVisibility.DIRECT) { - throw CrudExeption.badRequest("Direct Channel creation error: bad workspace"); + throw CrudException.badRequest("Direct Channel creation error: bad workspace"); } const directChannel = await this.getDirectChannelInCompany( context.workspace.company_id, options.members, + context, ); if (directChannel) { logger.debug("Direct channel already exists %o", directChannel); - const existingChannel = await this.channelRepository.findOne({ - company_id: context.workspace.company_id, - workspace_id: ChannelType.DIRECT, - id: directChannel.channel_id, - }); + const existingChannel = await this.channelRepository.findOne( + { + company_id: context.workspace.company_id, + workspace_id: ChannelType.DIRECT, + id: directChannel.channel_id, + }, + {}, + context, + ); if (existingChannel) { - const last_activity = await this.getChannelActivity(existingChannel); + const last_activity = await this.getChannelActivity(existingChannel, context); const saveResult = new SaveResult( "channels", @@ -220,12 +219,12 @@ export class Service implements ChannelService { return saveResult; } else { //Fixme: remove directChannel instance - throw CrudExeption.badRequest("table inconsistency"); + throw CrudException.badRequest("table inconsistency"); } } } else { if (!channel.name) { - throw CrudExeption.badRequest("'name' is required"); + throw CrudException.badRequest("'name' is required"); } } @@ -233,12 +232,21 @@ export class Service implements ChannelService { channelToSave.owner = context.user.id; } - const channelActivity = await this.activityRepository.findOne({ - channel_id: channel.id, - }); + const channelActivity = await this.activityRepository.findOne( + { + channel_id: channel.id, + }, + {}, + context, + ); logger.info("Saving channel %o", channelToSave); - await this.channelRepository.save(channelToSave); + await this.channelRepository.save(channelToSave, context); + + if (!isDirectChannel) { + channel.members = []; //Members is specific to direct channels + } + const saveResult = new SaveResult( "channel", { @@ -252,14 +260,33 @@ export class Service implements ChannelService { await this.addContextUserToChannel(context, saveResult); await this.onSaved(channelToSave, options, context, saveResult, mode); + // Shortcut to invite members to a channel + if (!isDirectChannel && options.members && options.members.length > 0) { + await gr.services.channels.members.addUsersToChannel( + options.members.map(id => { + return { id }; + }), + saveResult.entity, + context, + ); + } + return saveResult; } - async get(pk: ChannelPrimaryKey): Promise { + async get(pk: ChannelPrimaryKey, context?: ExecutionContext): Promise { const primaryKey = this.getPrimaryKey(pk); - const channel = await this.channelRepository.findOne(primaryKey); + let channel = await this.channelRepository.findOne(primaryKey); + if (!channel) { + channel = await this.channelRepository.findOne({ ...primaryKey, workspace_id: "direct" }); + } + if (!channel) return null; + const last_activity = await this.getChannelActivity(channel); + if (channel.visibility === ChannelVisibility.DIRECT) + channel = await this.includeUsersInDirectChannel(channel); + return ChannelObject.mapTo(channel, { last_activity }); } @@ -269,15 +296,19 @@ export class Service implements ChannelService { path: getChannelPath(channel, context as WorkspaceExecutionContext), }, ]) - async update(pk: ChannelPrimaryKey, channel: Channel): Promise> { + async update( + pk: ChannelPrimaryKey, + channel: Channel, + context: ExecutionContext, + ): Promise> { // TODO: Do the update by hand then save if (!pk.id) { - throw CrudExeption.badRequest("Channel id is required for update"); + throw CrudException.badRequest("Channel id is required for update"); } // eslint-disable-next-line @typescript-eslint/no-explicit-any const mergeChannel: any = { ...channel, ...pk }; - await this.channelRepository.save(mergeChannel as Channel); + await this.channelRepository.save(mergeChannel as Channel, context); return new UpdateResult("channel", ChannelObject.mapTo(mergeChannel)); } @@ -292,28 +323,31 @@ export class Service implements ChannelService { pk: ChannelPrimaryKey, context: WorkspaceExecutionContext, ): Promise> { - const channelToDelete = await this.channelRepository.findOne(this.getPrimaryKey(pk)); + const channelToDelete = await this.channelRepository.findOne( + this.getPrimaryKey(pk), + {}, + context, + ); if (!channelToDelete) { - throw new CrudExeption("Channel not found", 404); + throw new CrudException("Channel not found", 404); } const directChannel = isDirectChannel(channelToDelete); if (directChannel) { - throw new CrudExeption("Direct channel can not be deleted", 400); + throw new CrudException("Direct channel can not be deleted", 400); } const isWorkspaceAdmin = - !directChannel && - (await userIsWorkspaceAdmin(this.userService, context.user, context.workspace)); + !directChannel && (await userIsWorkspaceAdmin(context.user, context.workspace)); const isChannelOwner = this.isChannelOwner(channelToDelete, context.user); if (!isWorkspaceAdmin && !isChannelOwner) { - throw new CrudExeption("Channel can not be deleted", 400); + throw new CrudException("Channel can not be deleted", 400); } - await this.channelRepository.remove(channelToDelete); + await this.channelRepository.remove(channelToDelete, context); const result = new DeleteResult("channel", ChannelObject.mapTo(pk as Channel), true); this.onDeleted(channelToDelete, result); @@ -356,14 +390,19 @@ export class Service implements ChannelService { ): Promise> { const channelPK = payload.channel; const channelActivityMessage = payload.message; - const channel = await this.channelRepository.findOne( + const channel = (await this.channelRepository.findOne( _.pick(channelPK, "company_id", "workspace_id", "id"), - ); + {}, + context, + )) as ChannelObject & { stats: ChannelObject["stats"] }; + await gr.services.channels.channels.completeWithStatistics([channel]); + const entity = new ChannelActivity(); entity.channel_id = channelPK.id; entity.company_id = channelPK.company_id; entity.workspace_id = channelPK.workspace_id; entity.last_activity = payload.date; + entity.stats = channel.stats; entity.last_message = channelActivityMessage ? { date: channelActivityMessage.date, @@ -378,11 +417,11 @@ export class Service implements ChannelService { logger.info(`Update activity for channel ${entity.channel_id} to ${entity.last_activity}`); - await this.activityRepository.save(entity); + await this.activityRepository.save(entity, context); return new UpdateResult("channel_activity", entity); } - private async getChannelActivity(channel: Channel): Promise { + public async getChannelActivity(channel: Channel, context?: ExecutionContext): Promise { let result = 0; if (!channel) { @@ -390,11 +429,15 @@ export class Service implements ChannelService { } try { - const activity = await this.activityRepository.findOne({ - company_id: channel.company_id, - workspace_id: channel.workspace_id, - channel_id: channel.id, - } as ChannelActivity); + const activity = await this.activityRepository.findOne( + { + company_id: channel.company_id, + workspace_id: channel.workspace_id, + channel_id: channel.id, + } as ChannelActivity, + {}, + context, + ); result = activity?.last_activity || 0; } catch (error) { @@ -403,104 +446,180 @@ export class Service implements ChannelService { return result; } + public async fillChannelActivities( + channels: Channel[], + context: ExecutionContext, + ): Promise { + const filledChannels: ChannelObject[] = []; + for (const channel of channels) { + const activity = await this.getChannelActivity(channel, context); + const chObj = ChannelObject.mapTo(channel); + chObj.last_activity = activity; + filledChannels.push(chObj); + } + return filledChannels; + } + async list( pagination: Pagination, options: ChannelListOptions, context: WorkspaceExecutionContext, ): Promise> { - let channels: ListResult; - let activityPerChannel: Map; const isDirectWorkspace = isDirectChannel(context.workspace); const isWorkspaceAdmin = - !isDirectWorkspace && userIsWorkspaceAdmin(this.userService, context.user, context.workspace); + !isDirectWorkspace && userIsWorkspaceAdmin(context.user, context.workspace); const findFilters: FindFilter = { company_id: context.workspace.company_id, workspace_id: context.workspace.workspace_id, }; - if (options?.mine || isDirectWorkspace) { - const userChannels = await this.channelService.members.listUserChannels( - context.user, + let user_id = context.user.id; + if (context.user.application_id) { + user_id = user_id || options.user_id; + } + + if ((options?.mine || isDirectWorkspace) && user_id) { + if (!context.user.application_id && !context.user.server_request) { + localEventBus.publish("channel:list", { + user: context.user, + company: { + id: context.workspace.company_id, + }, + }); + } + + return this.getChannelsForUsersInWorkspace( + context.workspace.company_id, + context.workspace.workspace_id, + context.user.id, pagination, context, ); + } - channels = await this.channelRepository.find(findFilters, { - $in: [["id", userChannels.getEntities().map(channelMember => channelMember.channel_id)]], - }); - - if (!channels.isEmpty()) { - const activities = await this.activityRepository.find(findFilters, { - $in: [["channel_id", channels.getEntities().map(channel => channel.id)]], - }); + const channels = await this.channelRepository.find(findFilters, { pagination }, context); + channels.filterEntities(channel => channel.visibility !== ChannelVisibility.DIRECT); - activityPerChannel = new Map( - activities.getEntities().map(activity => [activity.channel_id, activity]), - ); - } else { - activityPerChannel = new Map(); - } + if (!isWorkspaceAdmin && !context.user.server_request) { + channels.filterEntities(channel => channel.visibility === ChannelVisibility.PUBLIC); + } - channels.mapEntities((channel: Channel) => { - const userChannel = find(userChannels.getEntities(), { channel_id: channel.id }); + return channels; + } - const channelActivity = activityPerChannel.get(channel.id); + async getChannelsForUsersInWorkspace( + companyId: string, + workspaceId: string | "direct", + userId: string, + pagination?: Pagination, + context?: ExecutionContext, + ): Promise> { + const isDirectWorkspace = isDirectChannel({ workspace_id: workspaceId }); + const findFilters: FindFilter = { + company_id: companyId, + workspace_id: workspaceId, + }; - return { - ...channel, - ...{ user_member: userChannel }, - last_activity: channelActivity?.last_activity || 0, - last_message: channelActivity?.last_message || {}, - } as unknown as UserChannel; - }); + const userChannels = await gr.services.channels.members.listUserChannels( + { id: userId }, + pagination, + { + user: { + id: userId, + }, + workspace: { + workspace_id: workspaceId, + company_id: companyId, + }, + }, + ); - if (isDirectWorkspace) { - channels.mapEntities((channel: UserChannel) => { - return { - ...channel, - ...{ - members: channel.members || [], - }, - } as unknown as UserDirectChannel; - }); - } + let activityPerChannel: Map; + const channels = await this.channelRepository.find( + findFilters, + { + $in: [["id", userChannels.getEntities().map(channelMember => channelMember.channel_id)]], + }, + context, + ); - localEventBus.publish("channel:list", { - user: context.user, - company: { - id: context.workspace.company_id, + if (!channels.isEmpty()) { + const activities = await this.activityRepository.find( + findFilters, + { + $in: [["channel_id", channels.getEntities().map(channel => channel.id)]], }, - }); + context, + ); - return new ListResult(channels.type, channels.getEntities(), userChannels.nextPage); + activityPerChannel = new Map( + activities.getEntities().map(activity => [activity.channel_id, activity]), + ); + } else { + activityPerChannel = new Map(); } - channels = await this.channelRepository.find(findFilters, { pagination }); - channels.filterEntities(channel => channel.visibility !== ChannelVisibility.DIRECT); + channels.mapEntities((channel: Channel) => { + const userChannel = find(userChannels.getEntities(), { channel_id: channel.id }); - if (!isWorkspaceAdmin && !context.user.server_request) { - channels.filterEntities(channel => channel.visibility === ChannelVisibility.PUBLIC); + const channelActivity = activityPerChannel.get(channel.id); + + return { + ...channel, + ...{ user_member: userChannel }, + last_activity: channelActivity?.last_activity || 0, + last_message: channelActivity?.last_message || {}, + } as unknown as UserChannel; + }); + + if (isDirectWorkspace) { + channels.mapEntities((channel: UserChannel) => { + return { + ...channel, + ...{ + members: channel.members || [], + }, + } as unknown as UserDirectChannel; + }); } - return channels; + return new ListResult( + channels.type, + channels.getEntities() as UserChannel[], + userChannels.nextPage, + ); } - async createDirectChannel(directChannel: DirectChannel): Promise { + async createDirectChannel( + directChannel: DirectChannel, + context: ExecutionContext, + ): Promise { const instance = getDirectChannelInstance(directChannel); - await this.directChannelRepository.save(instance); + await this.directChannelRepository.save(instance, context); return instance; } - getDirectChannel(directChannel: DirectChannel): Promise { - return this.directChannelRepository.findOne(directChannel); + getDirectChannel( + directChannel: DirectChannel, + context: ExecutionContext, + ): Promise { + return this.directChannelRepository.findOne(directChannel, {}, context); } - async getDirectChannelInCompany(companyId: string, users: string[]): Promise { - const directChannel = await this.directChannelRepository.findOne({ - company_id: companyId, - users: DirectChannel.getUsersAsString(users), - }); + async getDirectChannelInCompany( + companyId: string, + users: string[], + context: ExecutionContext, + ): Promise { + const directChannel = await this.directChannelRepository.findOne( + { + company_id: companyId, + users: DirectChannel.getUsersAsString(users), + }, + {}, + context, + ); return directChannel; } @@ -508,16 +627,19 @@ export class Service implements ChannelService { async getDirectChannelsInCompany( pagination: Pagination, company_id: string, + context: ExecutionContext, ): Promise> { return await this.channelRepository.find( { company_id, workspace_id: "direct" }, { pagination }, + context, ); } async getDirectChannelsForUsersInCompany( companyId: string, userId: string, + context: ExecutionContext, ): Promise { const list = await this.directChannelRepository.find( { @@ -526,31 +648,44 @@ export class Service implements ChannelService { { $like: [["users", userId]], }, + context, ); return list.getEntities(); } - async markAsRead(pk: ChannelPrimaryKey, user: User): Promise { + async markAsRead( + pk: ChannelPrimaryKey, + user: Pick, + context: ExecutionContext, + ): Promise { const now = Date.now(); - const channel = await this.get(pk); + let channel = await this.get(pk, context); if (!channel) { - throw CrudExeption.notFound("Channel not found"); + throw CrudException.notFound("Channel not found"); } - const member = await this.channelService.members.isChannelMember(user, channel); + await this.completeWithStatistics([channel]); + + const member = await gr.services.channels.members.getChannelMember( + user, + channel, + undefined, + context, + ); if (!member) { - throw CrudExeption.badRequest("User is not channel member"); + throw CrudException.badRequest("User is not channel member"); } - // Updating the member will also publish a message in the pubsub channel + // Updating the member will also publish a message in the message-queue channel // This message will be handled in the notification service and will update the notification preferences for the member // cf this.members.onUpdated member.last_access = now; + member.last_increment = channel.stats.messages; const updatedMember = ( - await this.channelService.members.save(member, null, { + await gr.services.channels.members.save(member, { channel, user, }) @@ -561,17 +696,21 @@ export class Service implements ChannelService { return true; } - async markAsUnread(pk: ChannelPrimaryKey, user: User): Promise { - const channel = await this.get(pk); + async markAsUnread( + pk: ChannelPrimaryKey, + user: User, + context: ExecutionContext, + ): Promise { + const channel = await this.get(pk, context); if (!channel) { - throw CrudExeption.notFound("Channel not found"); + throw CrudException.notFound("Channel not found"); } - const member = await this.channelService.members.isChannelMember(user, channel); + const member = await gr.services.channels.members.getChannelMember(user, channel); if (!member) { - throw CrudExeption.badRequest("User is not channel member"); + throw CrudException.badRequest("User is not channel member"); } // do nothing here but send a notification so that notification service is updated... @@ -612,7 +751,7 @@ export class Service implements ChannelService { //Add requester as member if (context.user.id) { try { - await this.channelService.members.addUserToChannels({ id: context.user.id }, [ + await gr.services.channels.members.addUserToChannels({ id: context.user.id }, [ savedChannel, ]); } catch (err) { @@ -623,19 +762,22 @@ export class Service implements ChannelService { public async includeUsersInDirectChannel( channel: Channel, - context?: WorkspaceExecutionContext, + excludeUserId?: string, ): Promise { const channelWithUsers: UsersIncludedChannel = { users: [], ...channel }; if (isDirectChannel(channel)) { const users = []; for (const user of channel.members) { - const e = await this.userService.formatUser(await this.userService.users.get({ id: user })); - users.push(e); + if (user) { + const e = await formatUser(await gr.services.users.getCached({ id: user })); + if (e) users.push(e); + } } channelWithUsers.users = users; channelWithUsers.name = users - .filter(u => u.id != context?.user?.id) - .map(u => u.full_name) + .filter(u => u.id != excludeUserId) + .map(u => u.full_name?.trim()) + .filter(a => a) .join(", "); } return channelWithUsers; @@ -664,11 +806,11 @@ export class Service implements ChannelService { users: DirectChannel.getUsersAsString(options.members), } as DirectChannel; - await this.createDirectChannel(directChannel); + await this.createDirectChannel(directChannel, context); } else { if (options.addCreatorAsMember && savedChannel.owner) { try { - await this.channelService.members.addUserToChannels({ id: savedChannel.owner }, [ + await gr.services.channels.members.addUserToChannels({ id: savedChannel.owner }, [ savedChannel, ]); } catch (err) { @@ -690,6 +832,15 @@ export class Service implements ChannelService { channel, user: context.user, }); + + localEventBus.publish>( + KnowledgeGraphEvents.CHANNEL_CREATED, + { + id: channel.id, + resource: channel, + links: [], + }, + ); } } @@ -707,35 +858,101 @@ export class Service implements ChannelService { /** * Called when a channel as been marked as read. - * Will publish `channel:read` notification in the pubsub service + * Will publish `channel:read` notification in the message-queue service * * @param channel * @param member */ - @PubsubPublish("channel:read") - onRead( - @PubsubParameter("channel") - channel: Channel, - @PubsubParameter("member") - member: ChannelMember, - ): void { + onRead(channel: Channel, member: ChannelMember): void { logger.info(`Channel ${channel.id} as been marked as read for user ${member.id}`); + + gr.platformServices.messageQueue.publish("channel:read", { + data: { + channel, + member, + }, + }); } /** * Called when a channel as been marked as unread. - * Will publish `channel:unread` notification in the pubsub service + * Will publish `channel:unread` notification in the message-queue service * * @param channel * @param member */ - @PubsubPublish("channel:unread") - onUnread( - @PubsubParameter("channel") - channel: Channel, - @PubsubParameter("member") - member: ChannelMember, - ): void { + onUnread(channel: Channel, member: ChannelMember): void { logger.info(`Channel ${channel.id} as been marked as unread for user ${member.id}`); + + gr.platformServices.messageQueue.publish("channel:unread", { + data: { + channel, + member, + }, + }); + } + + async search( + pagination: Pagination, + options: SearchChannelOptions, + context: ExecutionContext, + ): Promise> { + const rep = gr.platformServices.search.getRepository("channel", Channel); + return rep.search( + {}, + { + pagination, + ...(options.companyId ? { $in: [["company_id", [options.companyId]]] } : {}), + $text: { + $search: options.search, + }, + }, + context, + ); + } + + async getAllChannelsInWorkspace( + company_id: string, + workspace_id: string, + context?: ExecutionContext, + ): Promise { + let pagination = new Pagination(null, "100"); + + const channels: Channel[] = []; + do { + const res = await this.channelRepository.find( + { + company_id: company_id, + workspace_id: workspace_id, + }, + { + pagination, + }, + context, + ); + pagination = new Pagination(res.nextPage.page_token, res.nextPage.limitStr); + channels.push(...res.getEntities()); + } while (pagination.page_token); + + return channels; + } + + async completeWithStatistics( + channels: Pick[], + ) { + await Promise.all( + channels.map(async a => { + const members = await gr.services.channels.members.getUsersCount({ + ..._.pick(a, "id", "company_id", "workspace_id"), + counter_type: ChannelUserCounterType.MEMBERS, + }); + //Fixme: even if it works strange to use "getUsersCount" to get messages count + const messages = await gr.services.channels.members.getUsersCount({ + ..._.pick(a, "id", "company_id", "workspace_id"), + counter_type: ChannelUserCounterType.MESSAGES, + }); + a.stats = { members, messages }; + }), + ); } } diff --git a/twake/backend/node/src/services/channels/services/channel/types.ts b/twake/backend/node/src/services/channels/services/channel/types.ts index bab5d4f41d..76a4785519 100644 --- a/twake/backend/node/src/services/channels/services/channel/types.ts +++ b/twake/backend/node/src/services/channels/services/channel/types.ts @@ -2,6 +2,7 @@ import { merge } from "lodash"; import { Channel } from "../../entities/channel"; import { ChannelActivity } from "../../entities/channel-activity"; import { ChannelMember } from "../../entities"; +import { UserObject } from "../../../user/web/types"; export type NewUserInWorkspaceNotification = { user_id: string; @@ -11,7 +12,6 @@ export type NewUserInWorkspaceNotification = { export type ChannelStats = { members: number; - guests: number; messages: number; }; @@ -35,6 +35,9 @@ export class ChannelMemberObject extends ChannelMember { } return merge(new ChannelMemberObject(), { + favorite: false, + last_increment: 0, + last_access: 0, ...channelMember, ...channelMemberLikeObject, }); @@ -47,7 +50,7 @@ export class ChannelObject extends Channel { default: boolean; type: ChannelType; user_member: ChannelMemberObject; - + users: UserObject[]; stats: ChannelStats; constructor() { @@ -68,3 +71,16 @@ export class ChannelObject extends Channel { }); } } + +export type SearchChannelOptions = { + search: string; + companyId?: string; +}; + +export type ChannelActivityMessage = { + date: number; + sender: string; + sender_name: string; + title: string; + text: string; +}; diff --git a/twake/backend/node/src/services/channels/services/index.ts b/twake/backend/node/src/services/channels/services/index.ts deleted file mode 100644 index d1cf125fd9..0000000000 --- a/twake/backend/node/src/services/channels/services/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import ChannelServiceAPI, { - ChannelPendingEmailService, - ChannelService, - MemberService, - TabService, -} from "../provider"; -import { getService as getChannelService } from "./channel"; -import { getService as getMemberService } from "./member"; -import { getService as getTabService } from "./tab"; -import { PubsubListener } from "./pubsub"; -import Activities from "./channel/activities/service"; -import { getService as getActivitiesService } from "./channel/activities"; -import UserServiceAPI from "../../user/api"; -import ChannelPendingEmailsService from "./channel/pending-emails/service"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - user: UserServiceAPI, -): ChannelServiceAPI { - return getServiceInstance(platformServices, user); -} -function getServiceInstance( - platformServices: PlatformServicesAPI, - user: UserServiceAPI, -): ChannelServiceAPI { - return new Service(platformServices, user); -} - -class Service implements ChannelServiceAPI { - version: "1"; - channels: ChannelService; - members: MemberService; - tabs: TabService; - activities: Activities; - pubsubListener: PubsubListener; - pendingEmails: ChannelPendingEmailService; - - constructor(platformServices: PlatformServicesAPI, user: UserServiceAPI) { - this.members = getMemberService(platformServices, this, user); - this.channels = getChannelService(platformServices, this, user); - this.tabs = getTabService(platformServices.database); - this.activities = getActivitiesService(platformServices.pubsub); - this.pubsubListener = new PubsubListener(this, platformServices.pubsub, user); - this.pendingEmails = new ChannelPendingEmailsService(platformServices.database, user, this); - } - - async init(): Promise { - try { - await Promise.all([ - this.activities.init(), - this.channels.init(), - this.members.init(), - this.tabs.init(), - this.pubsubListener.init(), - this.pendingEmails.init(), - ]); - } catch (err) { - console.error("Error while initializing channel", err); - } - - return this; - } -} diff --git a/twake/backend/node/src/services/channels/services/member/index.ts b/twake/backend/node/src/services/channels/services/member/index.ts deleted file mode 100644 index 7d20a70c51..0000000000 --- a/twake/backend/node/src/services/channels/services/member/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import ChannelServiceAPI, { MemberService } from "../../provider"; -import { Service } from "./service"; -import UserServiceAPI from "../../../user/api"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - channelService: ChannelServiceAPI, - userService: UserServiceAPI, -): MemberService { - return new Service(platformServices, channelService, userService); -} diff --git a/twake/backend/node/src/services/channels/services/member/service.ts b/twake/backend/node/src/services/channels/services/member/service.ts index 4eed50ac7f..65a743ecd2 100644 --- a/twake/backend/node/src/services/channels/services/member/service.ts +++ b/twake/backend/node/src/services/channels/services/member/service.ts @@ -1,23 +1,25 @@ import { getLogger, RealtimeDeleted, RealtimeSaved } from "../../../../core/platform/framework"; import { CreateResult, - CrudExeption, + CrudException, DeleteResult, + ExecutionContext, ListResult, OperationType, Pagination, SaveResult, UpdateResult, } from "../../../../core/platform/framework/api/crud-service"; -import ChannelServiceAPI, { MemberService } from "../../provider"; import { Channel as ChannelEntity, ChannelMember, ChannelMemberPrimaryKey, + ChannelMemberReadCursors, getChannelMemberInstance, getMemberOfChannelInstance, MemberOfChannel, + ReadSection, } from "../../entities"; import { ChannelExecutionContext, @@ -33,23 +35,24 @@ import { getMemberPath, getRoomName } from "./realtime"; import { ChannelListOptions, ChannelMemberSaveOptions } from "../../web/types"; import { ResourcePath } from "../../../../core/platform/services/realtime/types"; import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { - PubsubParameter, - PubsubPublish, -} from "../../../../core/platform/services/pubsub/decorators/publish"; -import { localEventBus } from "../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; import { plainToClass } from "class-transformer"; -import UserServiceAPI, { CompaniesServiceAPI } from "../../../user/api"; import { ChannelCounterEntity, ChannelCounterPrimaryKey, ChannelUserCounterType, TYPE as ChannelCounterEntityType, -} from "../../entities/channel_counters"; +} from "../../entities/channel-counters"; import { CounterProvider } from "../../../../core/platform/services/counter/provider"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; import { countRepositoryItems } from "../../../../utils/counters"; -import { getService as getCompanyService } from "../../../user/services/companies"; +import NodeCache from "node-cache"; +import { UserPrimaryKey } from "../../../user/entities/user"; +import { WorkspacePrimaryKey } from "../../../workspaces/entities/workspace"; + +import gr from "../../../global-resolver"; +import uuidTime from "uuid-time"; +import { CompanyExecutionContext } from "../../../../services/messages/types"; +import { ChannelObject } from "../channel/types"; const USER_CHANNEL_KEYS = [ "id", @@ -75,49 +78,46 @@ const CHANNEL_MEMBERS_KEYS = [ const logger = getLogger("channel.member"); -export class Service implements MemberService { +export class MemberServiceImpl { version: "1"; userChannelsRepository: Repository; channelMembersRepository: Repository; + channelMembersReadCursorRepository: Repository; private channelCounter: CounterProvider; - private companies: CompaniesServiceAPI; - - constructor( - private platformServices: PlatformServicesAPI, - private channelService: ChannelServiceAPI, - protected userService: UserServiceAPI, - ) { - this.companies = this.userService.companies; - } + private cache: NodeCache; async init(): Promise { try { - this.userChannelsRepository = await this.platformServices.database.getRepository( - "user_channels", - ChannelMember, - ); - this.channelMembersRepository = await this.platformServices.database.getRepository( + this.userChannelsRepository = await gr.database.getRepository("user_channels", ChannelMember); + this.channelMembersRepository = await gr.database.getRepository( "channel_members", MemberOfChannel, ); + this.channelMembersReadCursorRepository = await gr.database.getRepository( + "channel_members_read_cursors", + ChannelMemberReadCursors, + ); } catch (err) { logger.error({ err }, "Can not initialize channel member service"); } - const channelCountersRepository = - await this.platformServices.database.getRepository( - ChannelCounterEntityType, - ChannelCounterEntity, - ); + const channelCountersRepository = await gr.database.getRepository( + ChannelCounterEntityType, + ChannelCounterEntity, + ); - this.channelCounter = await this.platformServices.counter.getCounter( + this.channelCounter = await gr.platformServices.counter.getCounter( channelCountersRepository, ); - this.channelCounter.reviseCounter(async (pk: ChannelCounterPrimaryKey) => { - const type = ChannelUserCounterType.MEMBERS - ? ChannelMemberType.MEMBER - : ChannelMemberType.GUEST; + this.channelCounter.setReviseCallback(async (pk: ChannelCounterPrimaryKey) => { + if (pk.counter_type === ChannelUserCounterType.MESSAGES) { + return; + } + const type = + ChannelUserCounterType.MEMBERS === pk.counter_type + ? ChannelMemberType.MEMBER + : ChannelMemberType.GUEST; return countRepositoryItems( this.channelMembersRepository, { channel_id: pk.id, company_id: pk.company_id, workspace_id: pk.workspace_id }, @@ -125,6 +125,8 @@ export class Service implements MemberService { ); }, 400); + this.cache = new NodeCache({ stdTTL: 1, checkperiod: 120 }); + return this; } @@ -150,17 +152,20 @@ export class Service implements MemberService { }) async save( member: ChannelMember, - options: ChannelMemberSaveOptions, context: ChannelExecutionContext, ): Promise> { let memberToSave: ChannelMember; - const channel = await this.channelService.channels.get(context.channel); + const channel = await gr.services.channels.channels.get(context.channel, context); if (!channel) { - throw CrudExeption.notFound("Channel does not exists"); + throw CrudException.notFound("Channel does not exists"); } - const memberToUpdate = await this.userChannelsRepository.findOne(this.getPrimaryKey(member)); + const memberToUpdate = await this.userChannelsRepository.findOne( + this.getPrimaryKey(member), + {}, + context, + ); const mode = memberToUpdate ? OperationType.UPDATE : OperationType.CREATE; logger.debug(`MemberService.save - ${mode} member %o`, memberToUpdate); @@ -169,13 +174,14 @@ export class Service implements MemberService { const isCurrentUser = this.isCurrentUser(memberToUpdate, context.user); if (!isCurrentUser) { - throw CrudExeption.badRequest(`Channel member ${member.user_id} can not be updated`); + throw CrudException.badRequest(`Channel member ${member.user_id} can not be updated`); } const updatableParameters: Partial> = { notification_level: isCurrentUser, favorite: isCurrentUser, last_access: isCurrentUser, + last_increment: isCurrentUser, }; // Diff existing channel and input one, cleanup all the undefined fields for all objects @@ -189,7 +195,7 @@ export class Service implements MemberService { const updatableFields = fields.filter(field => updatableParameters[field]); if (!updatableFields.length) { - throw CrudExeption.badRequest("Current user can not update requested fields"); + throw CrudException.badRequest("Current user can not update requested fields"); } memberToSave = cloneDeep(memberToUpdate); @@ -202,14 +208,19 @@ export class Service implements MemberService { (memberToSave as any)[field] = member[field]; }); - await this.userChannelsRepository.save(memberToSave); + await this.saveChannelMember(memberToSave, context); this.onUpdated( context.channel, memberToSave, new UpdateResult("channel_member", memberToSave), ); } else { - const currentUserIsMember = !!(await this.isChannelMember(context.user, channel)); + const currentUserIsMember = !!(await this.getChannelMember( + context.user, + channel, + undefined, + context, + )); const isPrivateChannel = ChannelEntity.isPrivateChannel(channel); const isPublicChannel = ChannelEntity.isPublicChannel(channel); const isDirectChannel = ChannelEntity.isDirectChannel(channel); @@ -223,18 +234,15 @@ export class Service implements MemberService { // 2. The channel creator check is only here on channel creation if ( isChannelCreator || - (isPrivateChannel && currentUserIsMember) || isPublicChannel || + context.user.server_request || + (isPrivateChannel && currentUserIsMember) || (isDirectChannel && userIsDefinedInChannelUserList) ) { const memberToSave = { ...member, ...context.channel }; - const userChannel = getChannelMemberInstance(pick(memberToSave, ...USER_CHANNEL_KEYS)); - const channelMember = getMemberOfChannelInstance( - pick(memberToSave, ...CHANNEL_MEMBERS_KEYS), - ); - await this.userChannelsRepository.save(userChannel); - await this.channelMembersRepository.save(channelMember); + await this.saveChannelMember(memberToSave, context); + await this.usersCounterIncrease(channel, member.user_id); this.onCreated( channel, member, @@ -242,16 +250,18 @@ export class Service implements MemberService { new CreateResult("channel_member", memberToSave), ); } else { - throw CrudExeption.badRequest(`User ${member.user_id} is not allowed to join this channel`); + throw CrudException.badRequest( + `User ${member.user_id} is not allowed to join this channel`, + ); } } return new SaveResult("channel_member", member, mode); } - async get(pk: ChannelMemberPrimaryKey): Promise { + async get(pk: ChannelMemberPrimaryKey, context: ExecutionContext): Promise { // FIXME: Who can fetch a single member? - return await this.userChannelsRepository.findOne(this.getPrimaryKey(pk)); + return await this.userChannelsRepository.findOne(this.getPrimaryKey(pk), {}, context); } @RealtimeDeleted((member, context) => [ @@ -276,20 +286,20 @@ export class Service implements MemberService { pk: ChannelMemberPrimaryKey, context: ChannelExecutionContext, ): Promise> { - const memberToDelete = await this.userChannelsRepository.findOne(pk); - const channel = await this.channelService.channels.get(context.channel); + const memberToDelete = await this.userChannelsRepository.findOne(pk, {}, context); + const channel = await gr.services.channels.channels.get(context.channel, context); if (!channel) { - throw CrudExeption.notFound("Channel does not exists"); + throw CrudException.notFound("Channel does not exists"); } if (!memberToDelete) { - throw CrudExeption.notFound("Channel member not found"); + throw CrudException.notFound("Channel member not found"); } if (ChannelEntity.isDirectChannel(channel)) { if (!this.isCurrentUser(memberToDelete, context.user)) { - throw CrudExeption.badRequest("User can not remove other users from direct channel"); + throw CrudException.badRequest("User can not remove other users from direct channel"); } } @@ -297,12 +307,12 @@ export class Service implements MemberService { const canLeave = await this.canLeavePrivateChannel(context.user, channel); if (!canLeave) { - throw CrudExeption.badRequest("User can not leave the private channel"); + throw CrudException.badRequest("User can not leave the private channel"); } } - await this.userChannelsRepository.remove(getChannelMemberInstance(pk)); - await this.channelMembersRepository.remove(getMemberOfChannelInstance(pk)); + await this.userChannelsRepository.remove(getChannelMemberInstance(pk), context); + await this.channelMembersRepository.remove(getMemberOfChannelInstance(pk), context); await this.usersCounterIncrease(channel, pk.user_id, -1); this.onDeleted(memberToDelete, context.user, channel); @@ -318,21 +328,24 @@ export class Service implements MemberService { options: ChannelListOptions, context: ChannelExecutionContext, ): Promise> { - const channel = await this.channelService.channels.get({ - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - id: context.channel.id, - }); + const channel = await gr.services.channels.channels.get( + { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + id: context.channel.id, + }, + context, + ); if (!channel) { - throw CrudExeption.notFound("Channel not found"); + throw CrudException.notFound("Channel not found"); } if (ChannelEntity.isDirectChannel(channel) || ChannelEntity.isPrivateChannel(channel)) { - const isMember = await this.isChannelMember(context.user, channel); + const isMember = await this.getChannelMember(context.user, channel, undefined, context); - if (!isMember) { - throw CrudExeption.badRequest("User does not have enough rights to get channels"); + if (!isMember && !context.user.server_request) { + throw CrudException.badRequest("User does not have enough rights to get channels"); } } @@ -343,13 +356,14 @@ export class Service implements MemberService { channel_id: context.channel.id, }, { pagination }, + context, ); - const companyUsers = await this.userService.companies.getUsers( + const companyUsers = await gr.services.companies.getUsers( { group_id: context.channel.company_id, }, - {}, + new Pagination(), { userIds: result.getEntities().map(member => member.user_id) }, ); @@ -370,6 +384,39 @@ export class Service implements MemberService { ); } + async listAllUserChannelsIds( + user_id: string, + company_id: string, + workspace_id: string, + context: ExecutionContext, + ): Promise { + let pagination = new Pagination(null); + const channels: string[] = []; + let result: ListResult; + let hasMoreItems = true; + do { + result = await this.userChannelsRepository.find( + { + company_id, + workspace_id, + user_id, + }, + { pagination }, + context, + ); + if (result.isEmpty()) { + hasMoreItems = false; + } else { + result.getEntities().forEach(entity => { + channels.push(entity.channel_id); + }); + if (!result.nextPage.page_token) hasMoreItems = false; + else pagination = new Pagination(result.nextPage.page_token); + } + } while (hasMoreItems); + return channels; + } + async listUserChannels( user: User, pagination: Pagination, @@ -382,6 +429,7 @@ export class Service implements MemberService { user_id: user.id, }, { pagination }, + context, ); return new ListResult( @@ -406,12 +454,13 @@ export class Service implements MemberService { async addUsersToChannel( users: Pick[] = [], - channel: ChannelEntity, + channel: ChannelEntity & { stats: ChannelObject["stats"] }, + context?: ExecutionContext, ): Promise< ListResult<{ channel: ChannelEntity; added: boolean; member?: ChannelMember; err?: Error }> > { if (!channel) { - throw CrudExeption.badRequest("Channel is required"); + throw CrudException.badRequest("Channel is required"); } logger.debug( "Add users %o to channel %o", @@ -419,6 +468,8 @@ export class Service implements MemberService { channel.id, ); + await gr.services.channels.channels.completeWithStatistics([channel]); + const members: Array<{ channel: ChannelEntity; added: boolean; @@ -426,9 +477,9 @@ export class Service implements MemberService { err?: Error; }> = await Promise.all( users.map(async user => { - const context: ChannelExecutionContext = { + const channelContext: ChannelExecutionContext = { channel, - user, + user: context?.user || user, }; const member: ChannelMember = getChannelMemberInstance({ @@ -436,18 +487,18 @@ export class Service implements MemberService { company_id: channel.company_id, workspace_id: channel.workspace_id, user_id: user.id, + last_increment: channel.stats.messages, + last_access: Date.now(), } as ChannelMember); try { - const isAlreadyMember = await this.isChannelMember(user, channel); + const isAlreadyMember = await this.getChannelMember(user, channel, undefined, context); if (isAlreadyMember) { logger.debug("User %s is already member in channel %s", member.user_id, channel.id); return { channel, added: false }; } - const result = await this.save(member, null, context); - - await this.usersCounterIncrease(channel, user.id); + const result = await this.save(member, channelContext); return { channel, @@ -499,15 +550,13 @@ export class Service implements MemberService { }); try { - const isAlreadyMember = await this.isChannelMember(user, channel); + const isAlreadyMember = await this.getChannelMember(user, channel, undefined, context); if (isAlreadyMember) { logger.debug("User %s is already member in channel %s", member.user_id, channel.id); return { channel, added: false }; } - const result = await this.save(member, null, context); - - await this.usersCounterIncrease(channel, member.user_id); + const result = await this.save(member, context); return { channel, member: result.entity, added: true }; } catch (err) { @@ -520,32 +569,39 @@ export class Service implements MemberService { return new ListResult("channel_member", members); } - @PubsubPublish("channel:member:updated") onUpdated( - @PubsubParameter("channel") channel: Channel, - @PubsubParameter("member") member: ChannelMember, // eslint-disable-next-line @typescript-eslint/no-unused-vars updateResult: UpdateResult, ): void { logger.debug("Member updated %o", member); + + gr.platformServices.messageQueue.publish("channel:member:updated", { + data: { + channel, + member, + }, + }); } - @PubsubPublish("channel:member:created") onCreated( - @PubsubParameter("channel") channel: ChannelEntity, - @PubsubParameter("member") member: ChannelMember, - @PubsubParameter("user") user: User, // eslint-disable-next-line @typescript-eslint/no-unused-vars createResult: SaveResult, ): void { logger.debug("Member created %o", member); - // Not sure about this, we use it on Tracker + Activities + gr.platformServices.messageQueue.publish("channel:member:created", { + data: { + channel, + user, + member, + }, + }); + localEventBus.publish("channel:member:created", { channel, user, @@ -555,22 +611,23 @@ export class Service implements MemberService { }); } - @PubsubPublish("channel:member:deleted") - onDeleted( - @PubsubParameter("member") - member: ChannelMember, - @PubsubParameter("user") - user: User, - @PubsubParameter("channel") - channel: ChannelEntity, - ): void { + onDeleted(member: ChannelMember, user: User, channel: ChannelEntity): void { logger.debug("Member deleted %o", member); + gr.platformServices.messageQueue.publish("channel:member:deleted", { + data: { + channel, + user, + member, + }, + }); + localEventBus.publish("channel:member:deleted", { actor: user, resourcesBefore: [member], - channel: channel, + channel, user, + member, }); } @@ -578,17 +635,33 @@ export class Service implements MemberService { return String(member.user_id) === String(user.id); } - isChannelMember(user: User, channel: Channel): Promise { + async getChannelMember( + user: User, + channel: Partial>, + cacheTtlSec?: number, + context?: ExecutionContext, + ): Promise { if (!user) { return; } - return this.get({ - channel_id: channel.id, - company_id: channel.company_id, - workspace_id: channel.workspace_id, - user_id: user.id, - }); + if (cacheTtlSec) { + const pk = JSON.stringify({ user, channel }); + if (this.cache.has(pk)) return this.cache.get(pk); + const entity = await this.getChannelMember(user, channel, undefined, context); + this.cache.set(pk, entity, cacheTtlSec); + return entity; + } + + return this.get( + { + channel_id: channel.id, + company_id: channel.company_id, + workspace_id: channel.workspace_id, + user_id: user.id, + }, + context, + ); } getPrimaryKey( @@ -620,6 +693,220 @@ export class Service implements MemberService { } async isCompanyMember(companyId: string, userId: string): Promise { - return (await this.companies.getUserRole(companyId, userId)) != "guest"; + return (await gr.services.companies.getUserRole(companyId, userId)) != "guest"; + } + + private async saveChannelMember( + memberToSave: ChannelMember & Channel, + context: ExecutionContext, + ) { + const userChannel = getChannelMemberInstance(pick(memberToSave, ...USER_CHANNEL_KEYS)); + const channelMember = getMemberOfChannelInstance(pick(memberToSave, ...CHANNEL_MEMBERS_KEYS)); + await this.userChannelsRepository.save(userChannel, context); + await this.channelMembersRepository.save(channelMember, context); + } + + async ensureUserNotInWorkspaceIsNotInChannel( + userPk: UserPrimaryKey, + workspacePk: WorkspacePrimaryKey, + context: ExecutionContext, + ) { + const workspace = await gr.services.workspaces.get(workspacePk); + const member = await gr.services.workspaces.getUser({ + workspaceId: workspace.id, + userId: userPk.id, + }); + if (!member) { + const result = await this.userChannelsRepository.find( + { + company_id: workspace.company_id, + workspace_id: workspace.id, + user_id: userPk.id, + }, + {}, + context, + ); + for (const channel of result.getEntities()) { + logger.warn( + `User ${userPk.id} is not in workspace ${workspace.id} so it will be removed from channel ${channel.id}`, + ); + await this.delete(channel, { user: { id: userPk.id }, channel }); + } + } + } + + /** + * The list of members read sections of the channel. + * + * @param {ChannelExecutionContext} context - The context of the execution. + * @returns {Promise>} - The channel members read cursors. + */ + async getChannelMembersReadSections( + context: ChannelExecutionContext, + ): Promise> { + try { + const readCursors = await this.channelMembersReadCursorRepository.find( + { + company_id: context.channel.company_id, + channel_id: context.channel.id, + }, + { pagination: { limitStr: "100" } }, + context, + ); + + return new ListResult( + "channel_members_read_cursors", + readCursors.getEntities(), + ); + } catch (error) { + logger.error(error); + throw error; + } + } + + /** + * The channel member read section of the channel. + * + * @param {ChannelExecutionContext} context - The context of the execution. + * @returns {Promise} - The channel member read cursors. + */ + async getChannelMemberReadSections( + member: string, + context: ChannelExecutionContext, + ): Promise { + try { + const readCursors = await this.channelMembersReadCursorRepository.findOne( + { + company_id: context.channel.company_id, + channel_id: context.channel.id, + user_id: member, + }, + {}, + context, + ); + + return readCursors; + } catch (error) { + logger.error(error); + throw error; + } + } + + /** + * Updates the channel member read section. + * + * @param {{ start: string; end: string }} section - The section to save the cursor for. + * @param {CompanyExecutionContext & { channel_id: string }} context - The channel execution context. + * @returns {Promise>} - The result of the save operation. + */ + async setChannelMemberReadSections( + section: { start: string; end: string }, + context: CompanyExecutionContext & { channel_id: string; workspace_id: string }, + ): Promise> { + const member = await this.getChannelMember( + context.user, + { + id: context.channel_id, + company_id: context.company.id, + workspace_id: context.workspace_id, + }, + null, + context, + ); + + if (!member) { + throw CrudException.badRequest( + `User ${context.user.id} is not a member of channel ${context.channel_id}`, + ); + } + + const existingReadSection = await this.channelMembersReadCursorRepository.findOne( + { + company_id: context.company.id, + channel_id: context.channel_id, + user_id: context.user.id, + }, + {}, + context, + ); + + const { start, end } = section; + + if ( + !existingReadSection || + !existingReadSection.read_section || + !existingReadSection.read_section.length + ) { + const newMemberReadCursor = new ChannelMemberReadCursors(); + newMemberReadCursor.company_id = context.company.id; + newMemberReadCursor.channel_id = context.channel_id; + newMemberReadCursor.user_id = context.user.id; + newMemberReadCursor.read_section = [start, end] as ReadSection; + + await this.channelMembersReadCursorRepository.save(newMemberReadCursor, context); + + return new SaveResult( + "channel_members_read_cursors", + newMemberReadCursor, + OperationType.CREATE, + ); + } + + const updatedReadSection = { start, end }; + const [existingStart, existingEnd] = existingReadSection.read_section; + const existingStartTime = uuidTime.v1(existingStart); + const existingEndTime = uuidTime.v1(existingEnd); + const startTime = uuidTime.v1(start); + const endTime = uuidTime.v1(end); + + if (existingStartTime < startTime) { + updatedReadSection.start = existingStart; + } + + if (existingEndTime > endTime) { + updatedReadSection.end = existingEnd; + } + + if (existingStart === updatedReadSection.start && existingEnd === updatedReadSection.end) { + return new SaveResult( + "channel_members_read_cursors", + existingReadSection, + OperationType.EXISTS, + ); + } + + existingReadSection.read_section = [updatedReadSection.start, updatedReadSection.end]; + await this.channelMembersReadCursorRepository.save(existingReadSection, context); + + return new SaveResult( + "channel_members_read_cursors", + existingReadSection, + OperationType.UPDATE, + ); + } + + /** + * list users who have seen the message. + * + * @param {String} id - the message id + * @param {ChannelExecutionContext} context - the thread execution context + * @returns { Promise} - the promise containing the user id list + */ + async getChannelMessageSeenByUsers( + id: string, + context: ChannelExecutionContext, + ): Promise { + const channelReadSections = await this.getChannelMembersReadSections(context); + + return channelReadSections + .getEntities() + .filter(section => { + const sectionEnd = section.read_section[1]; + const sectionEndTime = uuidTime.v1(sectionEnd); + const messageTime = uuidTime.v1(id); + + return messageTime <= sectionEndTime; + }) + .map(section => section.user_id); } } diff --git a/twake/backend/node/src/services/channels/services/pubsub/index.ts b/twake/backend/node/src/services/channels/services/pubsub/index.ts index 563fec030e..e8d452e0ea 100644 --- a/twake/backend/node/src/services/channels/services/pubsub/index.ts +++ b/twake/backend/node/src/services/channels/services/pubsub/index.ts @@ -1,32 +1,23 @@ import { Initializable } from "../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; -import ChannelServiceAPI from "../../provider"; import { NewChannelActivityProcessor } from "./new-channel-activity"; import { NewDirectChannelMessageProcessor } from "./new-direct-channel-message"; import { NewUserInWorkspaceJoinDefaultChannelsProcessor } from "./new-user-in-workspace-join-default-channels"; import { NewPendingEmailsInWorkspaceJoinChannelsProcessor } from "./new-pending-emails-in-workspace-join-channels"; -import UserServiceAPI from "../../../user/api"; import { NewWorkspaceProcessor } from "./new-workspace"; +import gr from "../../../global-resolver"; -export class PubsubListener implements Initializable { - constructor( - private service: ChannelServiceAPI, - private pubsub: PubsubServiceAPI, - private user: UserServiceAPI, - ) {} - +export class ChannelsMessageQueueListener implements Initializable { async init(): Promise { - this.pubsub.processor.addHandler( - new NewChannelActivityProcessor(this.service.channels, this.user), - ); - this.pubsub.processor.addHandler(new NewDirectChannelMessageProcessor(this.service)); - this.pubsub.processor.addHandler( - new NewUserInWorkspaceJoinDefaultChannelsProcessor(this.service), + const channelActivityProcessor = await new NewChannelActivityProcessor().init(); + gr.platformServices.messageQueue.processor.addHandler(channelActivityProcessor); + gr.platformServices.messageQueue.processor.addHandler(new NewDirectChannelMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler( + new NewUserInWorkspaceJoinDefaultChannelsProcessor(), ); - this.pubsub.processor.addHandler( - new NewPendingEmailsInWorkspaceJoinChannelsProcessor(this.service), + gr.platformServices.messageQueue.processor.addHandler( + new NewPendingEmailsInWorkspaceJoinChannelsProcessor(), ); - this.pubsub.processor.addHandler(new NewWorkspaceProcessor(this.service)); + gr.platformServices.messageQueue.processor.addHandler(new NewWorkspaceProcessor()); return this; } diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity.ts b/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity.ts new file mode 100644 index 0000000000..127b2bd4cd --- /dev/null +++ b/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity.ts @@ -0,0 +1,91 @@ +import { getLogger } from "../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../core/platform/services/message-queue/api"; +import { ChannelActivityNotification } from "../../types"; +import { CounterProvider } from "../../../../core/platform/services/counter/provider"; +import { + ChannelCounterEntity, + ChannelUserCounterType, + TYPE as ChannelCounterEntityType, +} from "../../entities/channel-counters"; +import gr from "../../../global-resolver"; + +const logger = getLogger("channel.message-queue.new-channel-activity"); +export class NewChannelActivityProcessor + implements MessageQueueHandler +{ + private channelCounter: CounterProvider; + + async init() { + const channelCountersRepository = await gr.database.getRepository( + ChannelCounterEntityType, + ChannelCounterEntity, + ); + this.channelCounter = await gr.platformServices.counter.getCounter( + channelCountersRepository, + ); + return this; + } + + readonly topics = { + in: "channel:activity", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "NewChannelActivityProcessor"; + + validate(message: ChannelActivityNotification): boolean { + return !!(message && message.channel_id && message.company_id && message.workspace_id); + } + + async process(message: ChannelActivityNotification): Promise { + logger.info(`${this.name} - Processing new activity in channel ${message.channel_id}`); + + await this.channelCounter.increase( + { + id: message.channel_id, + company_id: message.company_id, + workspace_id: message.workspace_id, + counter_type: ChannelUserCounterType.MESSAGES, + }, + 1, + ); + + try { + await gr.services.channels.channels.updateLastActivity( + { + date: message.date, + channel: { + id: message.channel_id, + workspace_id: message.workspace_id, + company_id: message.company_id, + }, + message: { + date: message.date, + sender: message.sender, + sender_name: message.sender_name, + title: message.title, + text: message.body, + }, + }, + { + workspace: { + workspace_id: message.workspace_id, + company_id: message.company_id, + }, + user: { + id: message.sender, + }, + }, + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while applying channel new activity in channel ${message?.channel_id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts deleted file mode 100644 index ef242f9c8d..0000000000 --- a/twake/backend/node/src/services/channels/services/pubsub/new-channel-activity/index.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { getLogger } from "../../../../../core/platform/framework"; -import { PubsubHandler } from "../../../../../core/platform/services/pubsub/api"; -import { ChannelActivityNotification } from "../../../types"; -import { ChannelService } from "../../../provider"; -import UserServiceAPI from "../../../../user/api"; - -const logger = getLogger("channel.pubsub.new-channel-activity"); -export class NewChannelActivityProcessor - implements PubsubHandler { - constructor(readonly service: ChannelService, private user: UserServiceAPI) {} - - readonly topics = { - in: "channel:activity", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "NewChannelActivityProcessor"; - - validate(message: ChannelActivityNotification): boolean { - return !!(message && message.channel_id && message.company_id && message.workspace_id); - } - - async process(message: ChannelActivityNotification): Promise { - logger.info(`${this.name} - Processing new activity in channel ${message.channel_id}`); - - try { - this.service.updateLastActivity( - { - date: message.date, - channel: { - id: message.channel_id, - workspace_id: message.workspace_id, - company_id: message.company_id, - }, - message: { - date: message.date, - sender: message.sender, - sender_name: message.sender_name, - title: message.title, - text: message.body, - }, - }, - { - workspace: { - workspace_id: message.workspace_id, - company_id: message.company_id, - }, - user: { - id: message.sender, - }, - }, - ); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while applying channel new activity in channel ${message?.channel_id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message.ts b/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message.ts new file mode 100644 index 0000000000..9aee6a3652 --- /dev/null +++ b/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message.ts @@ -0,0 +1,93 @@ +import { without } from "lodash"; +import { Channel, ChannelMember } from "../../entities"; +import { getLogger } from "../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../core/platform/services/message-queue/api"; +import { MessageNotification } from "../../../messages/types"; +import gr from "../../../global-resolver"; +import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; + +const logger = getLogger("channel.message-queue.new-direct-channel-message"); + +export class NewDirectChannelMessageProcessor + implements MessageQueueHandler +{ + readonly topics = { + in: "message:created", + }; + + readonly options = { + unique: true, + ack: true, + queue: "message:created:consumer1", + }; + + readonly name = "Channel::NewDirectChannelMessageProcessor"; + + validate(message: MessageNotification): boolean { + return !!(message && message.channel_id && message.company_id && message.workspace_id); + } + + async process(message: MessageNotification, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing notification for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, + ); + logger.debug(`${this.name} - Notification message ${JSON.stringify(message)}`); + + try { + const channel = await gr.services.channels.channels.get( + { + company_id: message.company_id, + id: message.channel_id, + workspace_id: message.workspace_id, + }, + context, + ); + + if (!channel || !Channel.isDirectChannel(channel)) { + logger.debug(`${this.name} - Not a direct channel`); + return; + } + + const memberIds = without(channel.members || [], String(message.sender)); + if (!memberIds.length) { + logger.debug(`${this.name} - No members to notify. Original array was %o`, channel.members); + } + + const members = memberIds.map(user_id => { + return { + user_id, + channel_id: channel.id, + workspace_id: channel.workspace_id, + company_id: channel.company_id, + } as ChannelMember; + }); + + await Promise.all( + members.map(async member => { + try { + logger.info(`${this.name} - Adding ${member.user_id} to channel ${message.channel_id}`); + const memberSaved = await gr.services.channels.members.save(member, { + channel, + user: { id: member.user_id }, + }); + logger.info( + `${this.name} - Member added to channel ${message.channel_id} - ${JSON.stringify( + memberSaved, + )}`, + ); + } catch (err) { + logger.info( + { err }, + `${this.name} - Error while adding user ${member.user_id} to direct channel ${member.channel_id}`, + ); + } + }), + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while processing direct channel members for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message/index.ts deleted file mode 100644 index ae4d077620..0000000000 --- a/twake/backend/node/src/services/channels/services/pubsub/new-direct-channel-message/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { without } from "lodash"; -import { Channel, ChannelMember } from "../../../entities"; -import { getLogger } from "../../../../../core/platform/framework"; -import { PubsubHandler } from "../../../../../core/platform/services/pubsub/api"; -import { MessageNotification } from "../../../../messages/types"; -import ChannelServiceAPI from "../../../provider"; - -const logger = getLogger("channel.pubsub.new-direct-channel-message"); - -export class NewDirectChannelMessageProcessor implements PubsubHandler { - constructor(readonly service: ChannelServiceAPI) {} - - readonly topics = { - in: "message:created", - }; - - readonly options = { - unique: true, - ack: true, - queue: "message:created:consumer1", - }; - - readonly name = "Channel::NewDirectChannelMessageProcessor"; - - validate(message: MessageNotification): boolean { - return !!(message && message.channel_id && message.company_id && message.workspace_id); - } - - async process(message: MessageNotification): Promise { - logger.info( - `${this.name} - Processing notification for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, - ); - logger.debug(`${this.name} - Notification message ${JSON.stringify(message)}`); - - try { - const channel = await this.service.channels.get({ - company_id: message.company_id, - id: message.channel_id, - workspace_id: message.workspace_id, - }); - - if (!channel || !Channel.isDirectChannel(channel)) { - logger.debug(`${this.name} - Not a direct channel`); - return; - } - - const memberIds = without(channel.members || [], String(message.sender)); - if (!memberIds.length) { - logger.debug(`${this.name} - No members to notify. Original array was %o`, channel.members); - } - - const members = memberIds.map(user_id => { - return { - user_id, - channel_id: channel.id, - workspace_id: channel.workspace_id, - company_id: channel.company_id, - } as ChannelMember; - }); - - await Promise.all( - members.map(async member => { - try { - logger.info(`${this.name} - Adding ${member.user_id} to channel ${message.channel_id}`); - const memberSaved = await this.service.members.save( - member, - {}, - { channel, user: { id: member.user_id } }, - ); - logger.info( - `${this.name} - Member added to channel ${message.channel_id} - ${JSON.stringify( - memberSaved, - )}`, - ); - } catch (err) { - logger.info( - { err }, - `${this.name} - Error while adding user ${member.user_id} to direct channel ${member.channel_id}`, - ); - } - }), - ); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while processing direct channel members for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels.ts b/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels.ts new file mode 100644 index 0000000000..95c1a27863 --- /dev/null +++ b/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels.ts @@ -0,0 +1,58 @@ +import { getLogger } from "../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../core/platform/services/message-queue/api"; +import { NewUserInWorkspaceNotification } from "../channel/types"; +import gr from "../../../global-resolver"; +import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; + +const NAME = "Channel::NewPendingEmailsInWorkspaceJoinChannelsProcessor"; +const logger = getLogger( + "channel.message-queue.new-pending-emails-in-workspace-join-channels-processor", +); + +/** + * When a new pending email is added in a workspace, a `workspace:email:added` event is published. + * In such case, the email must be added to all the channels that he is invited. + */ +export class NewPendingEmailsInWorkspaceJoinChannelsProcessor + implements MessageQueueHandler +{ + readonly topics = { + in: "workspace:member:added", + }; + + readonly options = { + unique: true, + ack: true, + queue: "workspace:user:added:consumer_channel_pending_emails", + }; + + readonly name = NAME; + + validate(message: NewUserInWorkspaceNotification): boolean { + return !!(message && message.company_id && message.workspace_id && message.user_id); + } + + async process( + message: NewUserInWorkspaceNotification, + context?: ExecutionContext, + ): Promise { + logger.debug("Processing notification for message %o", message); + + try { + await gr.services.channelPendingEmail.proccessPendingEmails( + message, + { + workspace_id: message.workspace_id, + company_id: message.company_id, + }, + context, + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while processing message for pending emails %o`, + message, + ); + } + } +} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels/index.ts deleted file mode 100644 index 56dbfd7f58..0000000000 --- a/twake/backend/node/src/services/channels/services/pubsub/new-pending-emails-in-workspace-join-channels/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { getLogger } from "../../../../../core/platform/framework"; -import { PubsubHandler } from "../../../../../core/platform/services/pubsub/api"; -import ChannelServiceAPI from "../../../provider"; -import { NewUserInWorkspaceNotification } from "../../channel/types"; - -const NAME = "Channel::NewPendingEmailsInWorkspaceJoinChannelsProcessor"; -const logger = getLogger("channel.pubsub.new-pending-emails-in-workspace-join-channels-processor"); - -/** - * When a new pending email is added in a workspace, a `workspace:email:added` event is published. - * In such case, the email must be added to all the channels that he is invited. - */ -export class NewPendingEmailsInWorkspaceJoinChannelsProcessor - implements PubsubHandler { - constructor(readonly service: ChannelServiceAPI) {} - - readonly topics = { - in: "workspace:member:added", - }; - - readonly options = { - unique: true, - ack: true, - queue: "workspace:user:added:consumer_channel_pending_emails", - }; - - readonly name = NAME; - - validate(message: NewUserInWorkspaceNotification): boolean { - return !!(message && message.company_id && message.workspace_id && message.user_id); - } - - async process(message: NewUserInWorkspaceNotification): Promise { - logger.debug("Processing notification for message %o", message); - - try { - await this.service.pendingEmails.proccessPendingEmails(message, { - workspace_id: message.workspace_id, - company_id: message.company_id, - }); - - logger.debug("Pending email %s has been added as member to channel %o"); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while processing message for pending emails %o`, - message, - ); - } - } -} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels.ts b/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels.ts new file mode 100644 index 0000000000..e3f682c2c8 --- /dev/null +++ b/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels.ts @@ -0,0 +1,59 @@ +import { getLogger } from "../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../core/platform/services/message-queue/api"; +import { NewUserInWorkspaceNotification } from "../channel/types"; +import gr from "../../../global-resolver"; + +const NAME = "Channel::NewUserInWorkspaceJoinDefaultChannelsProcessor"; +const logger = getLogger( + "channel.message-queue.new-user-in-workspace-join-default-channels-processor", +); + +/** + * When a new user is added in a workspace, a `workspace:user:added` event is published. + * In such case, the user must be added to all the default channels of the workspace. + */ +export class NewUserInWorkspaceJoinDefaultChannelsProcessor + implements MessageQueueHandler +{ + readonly topics = { + in: "workspace:member:added", + }; + + readonly options = { + unique: true, + ack: true, + queue: "workspace:user:added:consumer_default_channels", + }; + + readonly name = NAME; + + validate(message: NewUserInWorkspaceNotification): boolean { + return !!(message && message.company_id && message.workspace_id && message.user_id); + } + + async process(message: NewUserInWorkspaceNotification): Promise { + logger.debug("Processing notification for message %o", message); + + try { + const channelMembers = await gr.services.channels.channels.addUserToDefaultChannels( + { id: message.user_id }, + { + company_id: message.company_id, + workspace_id: message.workspace_id, + }, + ); + + logger.debug( + "User %s has been added as member to default channels %o", + message.user_id, + (channelMembers || []).map(c => c.channel_id), + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while processing message for default channels %o`, + message, + ); + } + } +} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels/index.ts deleted file mode 100644 index b582576d7a..0000000000 --- a/twake/backend/node/src/services/channels/services/pubsub/new-user-in-workspace-join-default-channels/index.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { getLogger } from "../../../../../core/platform/framework"; -import { PubsubHandler } from "../../../../../core/platform/services/pubsub/api"; -import ChannelServiceAPI from "../../../provider"; -import { NewUserInWorkspaceNotification } from "../../channel/types"; - -const NAME = "Channel::NewUserInWorkspaceJoinDefaultChannelsProcessor"; -const logger = getLogger("channel.pubsub.new-user-in-workspace-join-default-channels-processor"); - -/** - * When a new user is added in a workspace, a `workspace:user:added` event is published. - * In such case, the user must be added to all the default channels of the workspace. - */ -export class NewUserInWorkspaceJoinDefaultChannelsProcessor - implements PubsubHandler -{ - constructor(readonly service: ChannelServiceAPI) {} - - readonly topics = { - in: "workspace:member:added", - }; - - readonly options = { - unique: true, - ack: true, - queue: "workspace:user:added:consumer_default_channels", - }; - - readonly name = NAME; - - validate(message: NewUserInWorkspaceNotification): boolean { - return !!(message && message.company_id && message.workspace_id && message.user_id); - } - - async process(message: NewUserInWorkspaceNotification): Promise { - logger.debug("Processing notification for message %o", message); - - try { - const channelMembers = await this.service.channels.addUserToDefaultChannels( - { id: message.user_id }, - { - company_id: message.company_id, - workspace_id: message.workspace_id, - }, - ); - - logger.debug( - "User %s has been added as member to default channels %o", - message.user_id, - (channelMembers || []).map(c => c.channel_id), - ); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while processing message for default channels %o`, - message, - ); - } - } -} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-workspace.ts b/twake/backend/node/src/services/channels/services/pubsub/new-workspace.ts new file mode 100644 index 0000000000..2803d49bc6 --- /dev/null +++ b/twake/backend/node/src/services/channels/services/pubsub/new-workspace.ts @@ -0,0 +1,57 @@ +import { getLogger } from "../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../core/platform/services/message-queue/api"; +import { ChannelActivityNotification, ChannelVisibility } from "../../types"; +import { getInstance } from "../../../channels/entities/channel"; +import gr from "../../../global-resolver"; + +const logger = getLogger("channel.message-queue.new-channel-activity"); +export class NewWorkspaceProcessor + implements MessageQueueHandler +{ + readonly topics = { + in: "workspace:added", + queue: "workspace:added:consumer1", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "NewWorkspaceProcessor"; + + validate(message: ChannelActivityNotification): boolean { + return !!(message && message.company_id && message.workspace_id); + } + + async process(message: ChannelActivityNotification): Promise { + logger.info(`${this.name} - Processing new workspace created ${message.workspace_id}`); + + try { + await gr.services.channels.channels.save( + getInstance({ + icon: "💬", + name: "General", + description: "", + visibility: ChannelVisibility.PUBLIC, + is_default: true, + }), + {}, + { + workspace: { + workspace_id: message.workspace_id, + company_id: message.company_id, + }, + user: { + id: message.sender, + }, + }, + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while generating default channels for workspace ${message?.workspace_id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/channels/services/pubsub/new-workspace/index.ts b/twake/backend/node/src/services/channels/services/pubsub/new-workspace/index.ts deleted file mode 100644 index 6d53c8d898..0000000000 --- a/twake/backend/node/src/services/channels/services/pubsub/new-workspace/index.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { getLogger } from "../../../../../core/platform/framework"; -import { PubsubHandler } from "../../../../../core/platform/services/pubsub/api"; -import { ChannelActivityNotification, ChannelVisibility } from "../../../types"; -import ChannelServiceAPI from "../../../provider"; -import { getInstance } from "../../../../channels/entities/channel"; - -const logger = getLogger("channel.pubsub.new-channel-activity"); -export class NewWorkspaceProcessor implements PubsubHandler { - constructor(readonly service: ChannelServiceAPI) {} - - readonly topics = { - in: "workspace:added", - queue: "workspace:added:consumer1", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "NewWorkspaceProcessor"; - - validate(message: ChannelActivityNotification): boolean { - return !!(message && message.company_id && message.workspace_id); - } - - async process(message: ChannelActivityNotification): Promise { - logger.info(`${this.name} - Processing new activity in channel ${message.channel_id}`); - - try { - await this.service.channels.save( - getInstance({ - icon: "💬", - name: "General", - description: "", - visibility: ChannelVisibility.PUBLIC, - is_default: true, - }), - {}, - { - workspace: { - workspace_id: message.workspace_id, - company_id: message.company_id, - }, - user: { - id: message.sender, - }, - }, - ); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while generating default channels for workspace ${message?.workspace_id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/channels/services/tab.ts b/twake/backend/node/src/services/channels/services/tab.ts new file mode 100644 index 0000000000..a6d124ee7d --- /dev/null +++ b/twake/backend/node/src/services/channels/services/tab.ts @@ -0,0 +1,136 @@ +import _ from "lodash"; +import { RealtimeDeleted, RealtimeSaved } from "../../../core/platform/framework"; +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Pagination, + SaveResult, + UpdateResult, +} from "../../../core/platform/framework/api/crud-service"; +import { ChannelTab, ChannelTabPrimaryKey } from "../entities"; +import { ChannelExecutionContext } from "../types"; +import { Channel } from "../../../utils/types"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import gr from "../../global-resolver"; + +export class TabServiceImpl { + version: "1"; + repository: Repository; + + async init(): Promise { + this.repository = await gr.database.getRepository("channel_tabs", ChannelTab); + return this; + } + + @RealtimeSaved((tab, context) => [ + { + room: ResourcePath.get(getTabsRealtimeRoom((context as ChannelExecutionContext).channel)), + path: getTabsRealtimeResourcePath(tab, (context as ChannelExecutionContext).channel), + }, + ]) + async save( + tab: ChannelTab, + options: SaveOptions, + context: ChannelExecutionContext, + ): Promise> { + const pk = { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + channel_id: context.channel.id, + id: tab.id, + }; + + let tabEntity = await this.repository.findOne(pk, {}, context); + if (!tabEntity || !tab.id) { + tabEntity = new ChannelTab(); + tabEntity = _.merge(tabEntity, pk); + tabEntity.owner = context.user.id; + } + + tabEntity = _.merge( + tabEntity, + _.pick(tab, ["name", "configuration", "application_id", "order"]), + ); + + await this.repository.save(tabEntity, context); + + return new SaveResult("channel_tabs", tabEntity, OperationType.CREATE); + } + + async get(tabPk: ChannelTabPrimaryKey, context: ChannelExecutionContext): Promise { + const pk = { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + channel_id: context.channel.id, + id: tabPk.id, + }; + return await this.repository.findOne(pk, {}, context); + } + + @RealtimeDeleted((tab, context) => [ + { + room: ResourcePath.get(getTabsRealtimeRoom((context as ChannelExecutionContext).channel)), + path: getTabsRealtimeResourcePath(tab, (context as ChannelExecutionContext).channel), + }, + ]) + async delete( + pk: ChannelTabPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const tabEntity = await this.repository.findOne(pk, {}, context); + if (tabEntity) { + await this.repository.remove(tabEntity, context); + } + + return new DeleteResult("channel_tabs", tabEntity, true); + } + + async list( + pagination: Pagination, + options: ListOptions, + context: ChannelExecutionContext, + ): Promise> { + const pk = { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + channel_id: context.channel.id, + }; + return await this.repository.find(pk, { pagination }, context); + } + + onUpdated( + channel: Channel, + tab: ChannelTab, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + updateResult: UpdateResult, + ): void { + console.log("Tab updated", tab); + } + + onCreated( + channel: Channel, + tab: ChannelTab, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + createResult: SaveResult, + ): void { + console.log("Tab created", tab); + } + + onDeleted(channel: Channel, tab: ChannelTab): void { + console.log("Tab deleted", tab); + } +} + +export function getTabsRealtimeRoom(channel: ChannelExecutionContext["channel"]): string { + return `/companies/${channel.company_id}/workspaces/${channel.workspace_id}/channels/${channel.id}/tabs`; +} + +export function getTabsRealtimeResourcePath( + tab: ChannelTab, + channel: ChannelExecutionContext["channel"], +): string { + return `/companies/${channel.company_id}/workspaces/${channel.workspace_id}/channels/${channel.id}/tabs/${tab.id}`; +} diff --git a/twake/backend/node/src/services/channels/services/tab/index.ts b/twake/backend/node/src/services/channels/services/tab/index.ts deleted file mode 100644 index 36c407bd97..0000000000 --- a/twake/backend/node/src/services/channels/services/tab/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { TabService } from "../../provider"; -import { Service } from "./service"; - -export function getService(databaseService: DatabaseServiceAPI): TabService { - return new Service(databaseService); -} diff --git a/twake/backend/node/src/services/channels/services/tab/service.ts b/twake/backend/node/src/services/channels/services/tab/service.ts deleted file mode 100644 index 1e50613c6f..0000000000 --- a/twake/backend/node/src/services/channels/services/tab/service.ts +++ /dev/null @@ -1,135 +0,0 @@ -import _ from "lodash"; -import { RealtimeSaved, RealtimeDeleted } from "../../../../core/platform/framework"; -import { - DeleteResult, - Pagination, - ListResult, - SaveResult, - OperationType, - UpdateResult, -} from "../../../../core/platform/framework/api/crud-service"; -import { TabService } from "../../provider"; -import { ChannelTab, ChannelTabPrimaryKey } from "../../entities"; -import { ChannelExecutionContext } from "../../types"; -import { Channel } from "../../../../utils/types"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { ResourcePath } from "../../../../core/platform/services/realtime/types"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; - -export class Service implements TabService { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI) {} - - async init(): Promise { - this.repository = await this.database.getRepository("channel_tabs", ChannelTab); - return this; - } - - @RealtimeSaved((tab, context) => [ - { - room: ResourcePath.get(getTabsRealtimeRoom((context as ChannelExecutionContext).channel)), - path: getTabsRealtimeResourcePath(tab, (context as ChannelExecutionContext).channel), - }, - ]) - async save( - tab: ChannelTab, - options: SaveOptions, - context: ChannelExecutionContext, - ): Promise> { - const pk = { - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - channel_id: context.channel.id, - id: tab.id, - }; - - let tabEntity = await this.repository.findOne(pk); - if (!tabEntity || !tab.id) { - tabEntity = new ChannelTab(); - tabEntity = _.merge(tabEntity, pk); - tabEntity.owner = context.user.id; - } - - tabEntity = _.merge( - tabEntity, - _.pick(tab, ["name", "configuration", "application_id", "order"]), - ); - - await this.repository.save(tabEntity); - - return new SaveResult("channel_tabs", tabEntity, OperationType.CREATE); - } - - async get(tabPk: ChannelTabPrimaryKey, context: ChannelExecutionContext): Promise { - const pk = { - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - channel_id: context.channel.id, - id: tabPk.id, - }; - return await this.repository.findOne(pk); - } - - @RealtimeDeleted((tab, context) => [ - { - room: ResourcePath.get(getTabsRealtimeRoom((context as ChannelExecutionContext).channel)), - path: getTabsRealtimeResourcePath(tab, (context as ChannelExecutionContext).channel), - }, - ]) - async delete(pk: ChannelTabPrimaryKey): Promise> { - const tabEntity = await this.repository.findOne(pk); - if (tabEntity) { - await this.repository.remove(tabEntity); - } - - return new DeleteResult("channel_tabs", tabEntity, true); - } - - async list( - pagination: Pagination, - options: ListOptions, - context: ChannelExecutionContext, - ): Promise> { - const pk = { - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - channel_id: context.channel.id, - }; - return await this.repository.find(pk, { pagination }); - } - - onUpdated( - channel: Channel, - tab: ChannelTab, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - updateResult: UpdateResult, - ): void { - console.log("Tab updated", tab); - } - - onCreated( - channel: Channel, - tab: ChannelTab, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - createResult: SaveResult, - ): void { - console.log("Tab created", tab); - } - - onDeleted(channel: Channel, tab: ChannelTab): void { - console.log("Tab deleted", tab); - } -} - -export function getTabsRealtimeRoom(channel: ChannelExecutionContext["channel"]): string { - return `/companies/${channel.company_id}/workspaces/${channel.workspace_id}/channels/${channel.id}/tabs`; -} - -export function getTabsRealtimeResourcePath( - tab: ChannelTab, - channel: ChannelExecutionContext["channel"], -): string { - return `/companies/${channel.company_id}/workspaces/${channel.workspace_id}/channels/${channel.id}/tabs/${tab.id}`; -} diff --git a/twake/backend/node/src/services/channels/types.ts b/twake/backend/node/src/services/channels/types.ts index 8da8e0fd96..20894579f0 100644 --- a/twake/backend/node/src/services/channels/types.ts +++ b/twake/backend/node/src/services/channels/types.ts @@ -1,5 +1,5 @@ import { ExecutionContext } from "../../core/platform/framework/api/crud-service"; -import { Workspace, Channel, uuid } from "../../utils/types"; +import { Channel, uuid, Workspace } from "../../utils/types"; export interface WorkspaceExecutionContext extends ExecutionContext { workspace: Workspace; diff --git a/twake/backend/node/src/services/channels/web/controllers/channel.ts b/twake/backend/node/src/services/channels/web/controllers/channel.ts index c8c5c653c2..04b65189b3 100644 --- a/twake/backend/node/src/services/channels/web/controllers/channel.ts +++ b/twake/backend/node/src/services/channels/web/controllers/channel.ts @@ -1,8 +1,9 @@ import { plainToClass } from "class-transformer"; import { FastifyReply, FastifyRequest } from "fastify"; import { - CreateResult, - CrudExeption, + CrudException, + ExecutionContext, + ListResult, Pagination, } from "../../../../core/platform/framework/api/crud-service"; import { CrudController } from "../../../../core/platform/services/webserver/types"; @@ -11,15 +12,11 @@ import { ChannelMember, ChannelPendingEmails, ChannelPendingEmailsPrimaryKey, + ChannelPrimaryKey, getChannelPendingEmailsInstance, UserChannel, + UsersIncludedChannel, } from "../../entities"; -import { - ChannelPendingEmailService, - ChannelPrimaryKey, - ChannelService, - MemberService, -} from "../../provider"; import { getWebsocketInformation, getWorkspaceRooms } from "../../services/channel/realtime"; import { BaseChannelsParameters, @@ -27,6 +24,7 @@ import { ChannelParameters, ChannelPendingEmailsDeleteQueryParameters, ChannelSaveOptions, + ChannelSearchQueryParameters, CreateChannelBody, ReadChannelBody, UpdateChannelBody, @@ -40,11 +38,12 @@ import { ResourceListResponse, ResourceUpdateResponse, } from "../../../../utils/types"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; import { getLogger } from "../../../../core/platform/framework/logger"; import _ from "lodash"; import { ChannelMemberObject, ChannelObject } from "../../services/channel/types"; -import { ChannelUserCounterType } from "../../entities/channel_counters"; +import { ChannelUserCounterType } from "../../entities/channel-counters"; +import gr from "../../../global-resolver"; +import { checkUserBelongsToCompany } from "../../../../utils/company"; const logger = getLogger("channel.controller"); @@ -57,13 +56,6 @@ export class ChannelCrudController ResourceDeleteResponse > { - constructor( - protected websockets: RealtimeServiceAPI, - protected service: ChannelService, - protected membersService: MemberService, - protected pendingEmails: ChannelPendingEmailService, - ) {} - getPrimaryKey(request: FastifyRequest<{ Params: ChannelParameters }>): ChannelPrimaryKey { return { id: request.params.id, @@ -78,68 +70,148 @@ export class ChannelCrudController ): Promise> { const context = getExecutionContext(request); - let channel = await this.service.get(this.getPrimaryKey(request), getExecutionContext(request)); + let channel: Channel | UsersIncludedChannel = await gr.services.channels.channels.get( + this.getPrimaryKey(request), + context, + ); if (!channel) { - throw CrudExeption.notFound(`Channel ${request.params.id} not found`); + throw CrudException.notFound(`Channel ${request.params.id} not found`); } if (Channel.isDirectChannel(channel) || Channel.isPrivateChannel(channel)) { - const isMember = await this.membersService.isChannelMember(request.currentUser, channel); + const isMember = await gr.services.channels.members.getChannelMember( + request.currentUser, + channel, + undefined, + context, + ); if (!isMember) { - throw CrudExeption.badRequest("User does not have enough rights to get channel"); + throw CrudException.badRequest("User does not have enough rights to get channel"); } } if (request.query.include_users) - channel = await this.service.includeUsersInDirectChannel( - channel, - getExecutionContext(request), - ); + channel = await gr.services.channels.channels.includeUsersInDirectChannel(channel); - const member = await this.membersService.get( + const member = await gr.services.channels.members.get( _.assign(new ChannelMember(), { channel_id: channel.id, workspace_id: channel.workspace_id, company_id: channel.company_id, user_id: context.user.id, }), - getChannelExecutionContext(request, channel), + context, ); + const channelObject = ChannelObject.mapTo(channel, { + user_member: ChannelMemberObject.mapTo(member), + }); + + await gr.services.channels.channels.completeWithStatistics([channelObject]); + return { - websocket: this.websockets.sign([getWebsocketInformation(channel)], context.user.id)[0], - resource: ChannelObject.mapTo(channel, { - user_member: ChannelMemberObject.mapTo(member), - stats: { - members: await this.membersService.getUsersCount({ - id: channel.id, - company_id: channel.company_id, - workspace_id: channel.workspace_id, - counter_type: ChannelUserCounterType.MEMBERS, - }), - guests: 0, // Since actually all users are now added to the channel as members, we are removing the guest counter for now. - // guests: await this.membersService.getUsersCount({ - // id: channel.id, - // company_id: channel.company_id, - // workspace_id: channel.workspace_id, - // counter_type: ChannelUserCounterType.GUESTS, - // }), - messages: 0, - }, - }), + websocket: gr.platformServices.realtime.sign( + [getWebsocketInformation(channel)], + context.user.id, + )[0], + resource: channelObject, }; } + async search( + request: FastifyRequest<{ + Querystring: ChannelSearchQueryParameters; + Params: { company_id: string }; + }>, + reply: FastifyReply, + ): Promise> { + if (request.query?.q?.length === 0) { + return this.recent(request); + } + + const context = getSimpleExecutionContext(request); + const userId = request.currentUser.id; + + await checkUserBelongsToCompany(request.currentUser.id, request.params.company_id); + + const limit = request.query.limit || 100; + + async function* getNextChannels(): AsyncIterableIterator { + let lastPageToken = null; + let channels: Channel[] = []; + let hasMore = true; + do { + channels = await gr.services.channels.channels + .search( + new Pagination(lastPageToken, limit.toString()), + { + search: request.query.q, + companyId: request.params.company_id, + }, + context, + ) + .then((a: ListResult) => { + lastPageToken = a.nextPage.page_token; + if (!lastPageToken) { + hasMore = false; + } + return a.getEntities(); + }); + + if (channels.length) { + for (const channel of channels) { + yield channel; + } + } else { + hasMore = false; + } + } while (hasMore); + } + + const channels = [] as (Channel & { user_member: ChannelMemberObject })[]; + + for await (const ch of getNextChannels()) { + const channelMember = await gr.services.channels.members.getChannelMember( + { id: request.currentUser.id }, + ch, + 50, + context, + ); + + //If not public channel and not member then ignore + if (!channelMember && ch.visibility !== "public") continue; + + //If public channel but not in the workspace then ignore + if ( + !channelMember && + !(await gr.services.workspaces.getUser({ workspaceId: ch.workspace_id, userId })) + ) + continue; + + const chWithUser = await gr.services.channels.channels.includeUsersInDirectChannel( + ch, + userId, + ); + + channels.push({ ...chWithUser, user_member: channelMember }); + if (channels.length == limit) { + break; + } + } + + await gr.services.channels.channels.completeWithStatistics(channels as ChannelObject[]); + + return { resources: channels }; + } + async getForPHP( request: FastifyRequest<{ Params: ChannelParameters }>, reply: FastifyReply, ): Promise { - const channel = await this.service.get( - this.getPrimaryKey(request), - getExecutionContext(request), - ); + const context = getExecutionContext(request); + const channel = await gr.services.channels.channels.get(this.getPrimaryKey(request), context); reply.send(channel); } @@ -168,31 +240,27 @@ export class ChannelCrudController } as ChannelSaveOptions; const context = getExecutionContext(request); - const channelResult = await this.service.save(entity, options, context); - - await this.membersService.addUsersToChannel( - options.members.map(userId => { - return { id: userId }; - }), - channelResult.entity, - ); + const channelResult = await gr.services.channels.channels.save(entity, options, context); logger.debug("reqId: %s - save - Channel %s created", request.id, channelResult.entity.id); - const member = await this.membersService.get( + const member = await gr.services.channels.members.get( _.assign(new ChannelMember(), { channel_id: channelResult.entity.id, workspace_id: channelResult.entity.workspace_id, company_id: channelResult.entity.company_id, user_id: context.user.id, }), - getChannelExecutionContext(request, channelResult.entity), + context, ); let entityWithUsers: Channel = channelResult.entity; if (request.query.include_users) - entityWithUsers = await this.service.includeUsersInDirectChannel(entityWithUsers, context); + entityWithUsers = await gr.services.channels.channels.includeUsersInDirectChannel( + entityWithUsers, + context.user.id, + ); const resultEntity = { ...entityWithUsers, @@ -204,7 +272,7 @@ export class ChannelCrudController } return { - websocket: this.websockets.sign( + websocket: gr.platformServices.realtime.sign( [getWebsocketInformation(channelResult.entity)], context.user.id, )[0], @@ -230,14 +298,14 @@ export class ChannelCrudController try { const context = getExecutionContext(request); - const result = await this.service.save(entity, {}, context); + const result = await gr.services.channels.channels.save(entity, {}, context); if (result.entity) { reply.code(201); } return { - websocket: this.websockets.sign( + websocket: gr.platformServices.realtime.sign( [getWebsocketInformation(result.entity)], context.user.id, )[0], @@ -258,16 +326,17 @@ export class ChannelCrudController //Fixme: this slow down the channel get operation. Once we stabilize the workspace:member:added event we can remove this if (context.workspace.workspace_id !== ChannelVisibility.DIRECT) { - await this.pendingEmails.proccessPendingEmails( + await gr.services.channelPendingEmail.proccessPendingEmails( { user_id: context.user.id, ...context.workspace, }, context.workspace, + context, ); } - const list = await this.service.list( + const list = await gr.services.channels.channels.list( new Pagination(request.query.page_token, request.query.limit), { ...request.query }, context, @@ -277,7 +346,9 @@ export class ChannelCrudController if (request.query.include_users) { entities = []; for (const e of list.getEntities()) { - entities.push(await this.service.includeUsersInDirectChannel(e, context)); + entities.push( + await gr.services.channels.channels.includeUsersInDirectChannel(e, context.user.id), + ); } } else { entities = list.getEntities(); @@ -285,34 +356,14 @@ export class ChannelCrudController const resources = entities.map(a => ChannelObject.mapTo(a)); - try { - await this.membersService.getUsersCount({ - ..._.pick(resources[0], "id", "company_id", "workspace_id"), - counter_type: ChannelUserCounterType.MEMBERS, - }); - } catch (e) { - console.log(e); - } - - const counts = await Promise.all( - resources.map(a => - this.membersService.getUsersCount({ - ..._.pick(a, "id", "company_id", "workspace_id"), - counter_type: ChannelUserCounterType.MEMBERS, - }), - ), - ); - - for (let i = 0; i < resources.length; i++) { - resources[i].stats = { members: counts[i], guests: 0, messages: 0 }; - } + await gr.services.channels.channels.completeWithStatistics(resources); return { ...{ resources: resources, }, ...(request.query.websockets && { - websockets: this.websockets.sign( + websockets: gr.platformServices.realtime.sign( getWorkspaceRooms(request.params, request.currentUser), request.currentUser.id, ), @@ -328,7 +379,7 @@ export class ChannelCrudController reply: FastifyReply, ): Promise { try { - const deleteResult = await this.service.delete( + const deleteResult = await gr.services.channels.channels.delete( this.getPrimaryKey(request), getExecutionContext(request), ); @@ -354,18 +405,18 @@ export class ChannelCrudController reply: FastifyReply, ): Promise { const read = request.body.value; - + const context = getExecutionContext(request); try { const result = read - ? await this.service.markAsRead( + ? await gr.services.channels.channels.markAsRead( this.getPrimaryKey(request), request.currentUser, - getExecutionContext(request), + context, ) - : await this.service.markAsUnread( + : await gr.services.channels.channels.markAsUnread( this.getPrimaryKey(request), request.currentUser, - getExecutionContext(request), + context, ); return result; } catch (err) { @@ -382,7 +433,7 @@ export class ChannelCrudController // eslint-disable-next-line @typescript-eslint/no-unused-vars reply: FastifyReply, ): Promise> { - const list = await this.pendingEmails.list( + const list = await gr.services.channelPendingEmail.list( new Pagination(request.query.page_token, request.query.limit), { ...request.query }, getChannelPendingEmailsExecutionContext(request), @@ -391,7 +442,7 @@ export class ChannelCrudController return { resources: list.getEntities(), ...(request.query.websockets && { - websockets: this.websockets.sign( + websockets: gr.platformServices.realtime.sign( getWorkspaceRooms(request.params, request.currentUser), request.currentUser.id, ), @@ -410,13 +461,14 @@ export class ChannelCrudController }>, // eslint-disable-next-line @typescript-eslint/no-unused-vars reply: FastifyReply, - ): Promise>> { - const pendingEmail = await this.pendingEmails.create( + ): Promise> { + const context = getSimpleExecutionContext(request); + const pendingEmail = await gr.services.channelPendingEmail.create( getChannelPendingEmailsInstance(request.body.resource), - getChannelPendingEmailsExecutionContext(request), + context, ); logger.debug("reqId: %s - save - PendingEmails input %o", request.id, pendingEmail.entity); - return { resource: pendingEmail }; + return { resource: pendingEmail.entity }; } async deletePendingEmails( @@ -425,18 +477,92 @@ export class ChannelCrudController // eslint-disable-next-line @typescript-eslint/no-unused-vars reply: FastifyReply, ): Promise { - const pendingEmail = await this.pendingEmails.delete( + const pendingEmail = await gr.services.channelPendingEmail.delete( getChannelPendingEmailsInstance({ channel_id: request.params.channel_id, company_id: request.params.company_id, workspace_id: request.params.workspace_id, email: request.params.email, }), - getChannelPendingEmailsExecutionContext(request), ); return { status: pendingEmail.deleted ? "success" : "error" }; } + + async recent( + request: FastifyRequest<{ + Querystring: { limit?: string }; + Params: Pick; + }>, + ): Promise> { + const companyId = request.params.company_id; + const userId = request.currentUser.id; + + const context = getSimpleExecutionContext(request); + const limit = parseInt(request.query.limit) || 100; + + const workspaces = ( + await gr.services.workspaces.getAllForUser({ userId }, { id: companyId }) + ).map(a => a.workspaceId); + + let channels: UserChannel[] = await gr.services.channels.channels + .getChannelsForUsersInWorkspace(companyId, "direct", userId, undefined, context) + .then(list => list.getEntities()); + + for (const workspaceId of workspaces) { + const workspaceChannels = await gr.services.channels.channels + .getChannelsForUsersInWorkspace(companyId, workspaceId, userId, undefined, context) + .then(list => list.getEntities()); + channels = [...channels, ...workspaceChannels]; + } + + channels = channels.sort( + (a, b) => + (b.last_activity || 0) / 100 + + (b.user_member.last_access || 0) - + ((a.user_member.last_access || 0) + (a.last_activity || 0) / 100), + ); + channels = channels.slice(0, 100); + + if (channels.length < limit) { + let otherChannels: UserChannel[] = []; + for (const workspaceId of workspaces) { + //Include channels we could join in this result + otherChannels = [ + ...otherChannels, + ...( + await gr.services.channels.channels.getAllChannelsInWorkspace( + companyId, + workspaceId, + context, + ) + ).map(ch => { + return { + ...ch, + user_member: null, + } as UserChannel; + }), + ]; + } + + channels = _.unionBy(channels, otherChannels, "id"); + } + + const userIncludedChannels: UsersIncludedChannel[] = await Promise.all( + channels.map(channel => { + return gr.services.channels.channels.includeUsersInDirectChannel(channel, userId); + }), + ); + + const resources = userIncludedChannels.slice(0, limit).map(r => ChannelObject.mapTo(r, {})); + await gr.services.channels.channels.completeWithStatistics(resources); + + await new Promise(r => setTimeout(r, 2000)); + + return { + resources, + }; + } } function getExecutionContext( @@ -491,3 +617,13 @@ function getChannelPendingEmailsExecutionContext( }, }; } + +function getSimpleExecutionContext(request: FastifyRequest): ExecutionContext { + return { + user: request.currentUser, + url: request.url, + method: request.routerMethod, + reqId: request.id, + transport: "http", + }; +} diff --git a/twake/backend/node/src/services/channels/web/controllers/member.ts b/twake/backend/node/src/services/channels/web/controllers/member.ts index 6f0f4f20b7..26ec13c24d 100644 --- a/twake/backend/node/src/services/channels/web/controllers/member.ts +++ b/twake/backend/node/src/services/channels/web/controllers/member.ts @@ -1,7 +1,11 @@ import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { CrudExeption, Pagination } from "../../../../core/platform/framework/api/crud-service"; -import { ChannelMember, ChannelMemberPrimaryKey } from "../../entities"; -import { MemberService } from "../../provider"; +import { CrudException, Pagination } from "../../../../core/platform/framework/api/crud-service"; +import { + ChannelMember, + ChannelMemberPrimaryKey, + ChannelMemberReadCursors, + ChannelMemberWithUser, +} from "../../entities"; import { ChannelMemberParameters, ChannelParameters, @@ -22,7 +26,8 @@ import { ResourceUpdateResponse, User, } from "../../../../utils/types"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import gr from "../../../global-resolver"; +import { formatUser } from "../../../../utils/users"; export class ChannelMemberCrudController implements @@ -33,8 +38,6 @@ export class ChannelMemberCrudController ResourceDeleteResponse > { - constructor(protected websockets: RealtimeServiceAPI, protected service: MemberService) {} - getPrimaryKey( request: FastifyRequest<{ Params: ChannelMemberParameters }>, ): ChannelMemberPrimaryKey { @@ -51,16 +54,13 @@ export class ChannelMemberCrudController reply: FastifyReply, ): Promise> { if (!isCurrentUser(request.params.member_id, request.currentUser)) { - throw CrudExeption.badRequest("User does not have enough rights to get member"); + throw CrudException.badRequest("User does not have enough rights to get member"); } - - const resource = await this.service.get( - this.getPrimaryKey(request), - getExecutionContext(request), - ); + const context = getExecutionContext(request); + const resource = await gr.services.channels.members.get(this.getPrimaryKey(request), context); if (!resource) { - throw CrudExeption.notFound(`Channel member ${request.params.member_id} not found`); + throw CrudException.notFound(`Channel member ${request.params.member_id} not found`); } return { @@ -82,7 +82,7 @@ export class ChannelMemberCrudController }); try { - const result = await this.service.save(entity, {}, getExecutionContext(request)); + const result = await gr.services.channels.members.save(entity, getExecutionContext(request)); if (result.entity) { reply.code(201); @@ -106,11 +106,11 @@ export class ChannelMemberCrudController }); if (!isCurrentUser(entity.user_id, request.currentUser)) { - throw CrudExeption.badRequest("Current user can not update this member"); + throw CrudException.badRequest("Current user can not update this member"); } try { - const result = await this.service.save(entity, {}, getExecutionContext(request)); + const result = await gr.services.channels.members.save(entity, getExecutionContext(request)); if (result.entity) { reply.code(200); @@ -129,7 +129,7 @@ export class ChannelMemberCrudController reply: FastifyReply, ): Promise { try { - const deleteResult = await this.service.delete( + const deleteResult = await gr.services.channels.members.delete( this.getPrimaryKey(request), getExecutionContext(request), ); @@ -157,29 +157,74 @@ export class ChannelMemberCrudController */ async list( request: FastifyRequest<{ - Querystring: PaginationQueryParameters & { company_role?: string }; + Querystring: PaginationQueryParameters & { company_role?: string; search?: string }; Params: ChannelParameters; }>, - ): Promise> { - const list = await this.service.list( - new Pagination(request.query.page_token, request.query.limit), - { company_role: request.query.company_role }, - getExecutionContext(request), - ); + ): Promise> { + let list: ChannelMember[] = []; + let nextPageToken: string = null; + const resources = []; + const context = getExecutionContext(request); + + if (request.query.search) { + const users = await gr.services.users.search( + new Pagination(request.query.page_token, request.query.limit), + { + search: request.query.search, + companyId: request.params.company_id, + }, + context, + ); + + nextPageToken = users.nextPage?.page_token; + + for (const user of users.getEntities()) { + const channelMember = await gr.services.channels.members.getChannelMember( + user, + { + company_id: request.params.company_id, + workspace_id: request.params.workspace_id, + id: request.params.id, + }, + undefined, + context, + ); + + if (channelMember) { + list.push(channelMember); + } + } + } else { + const channelMembers = await gr.services.channels.members.list( + new Pagination(request.query.page_token, request.query.limit), + { company_role: request.query.company_role }, + context, + ); + + nextPageToken = channelMembers.nextPage?.page_token; + list = channelMembers.getEntities(); + } + + for (const member of list) { + if (member) { + const user = await formatUser(await gr.services.users.getCached({ id: member.user_id }), { + includeCompanies: true, + }); + resources.push({ ...member, user }); + } + } return { ...{ - resources: list.getEntities(), + resources, }, ...(request.query.websockets && { - websockets: this.websockets.sign( + websockets: gr.platformServices.realtime.sign( getChannelRooms(request.params, request.currentUser), request.currentUser.id, ), }), - ...(list.page_token && { - next_page_token: list.page_token, - }), + next_page_token: nextPageToken, }; } @@ -192,10 +237,8 @@ export class ChannelMemberCrudController request: FastifyRequest<{ Params: ChannelMemberParameters }>, reply: FastifyReply, ): Promise { - const resource = await this.service.get( - this.getPrimaryKey(request), - getExecutionContext(request), - ); + const context = getExecutionContext(request); + const resource = await gr.services.channels.members.get(this.getPrimaryKey(request), context); if (!resource) { return reply.status(200).send({ has_access: false }); @@ -203,6 +246,55 @@ export class ChannelMemberCrudController return reply.status(200).send({ has_access: true }); } + + /** + * Lists the channel read sections for all members. + * + * @param {FastifyRequest<{ Params: ChannelParameters }>} request - the request object + * @param {FastifyReply} reply - the reply object + * @returns {Promise>} - the response + */ + async getAllChannelMembersReadSections( + request: FastifyRequest<{ Params: ChannelParameters }>, + reply: FastifyReply, + ): Promise> { + try { + const context = getExecutionContext(request); + const channelMembersReadSections = + await gr.services.channels.members.getChannelMembersReadSections(context); + + return { + resources: channelMembersReadSections.getEntities(), + }; + } catch (err) { + handleError(reply, err); + } + } + + /** + * Get the channel member read section for a user. + * + * @param {FastifyRequest<{ Params: ChannelMemberParameters }>} request - the request object + * @param {FastifyReply} reply - the reply object + * @returns {Promise>} - the read section for the member + */ + async getChannelMemberReadSections( + request: FastifyRequest<{ Params: ChannelMemberParameters }>, + reply: FastifyReply, + ): Promise> { + try { + const { member_id } = request.params; + const context = getExecutionContext(request); + const channelMembersReadSections = + await gr.services.channels.members.getChannelMemberReadSections(member_id, context); + + return { + resource: channelMembersReadSections, + }; + } catch (err) { + handleError(reply, err); + } + } } function getExecutionContext( diff --git a/twake/backend/node/src/services/channels/web/controllers/tab.ts b/twake/backend/node/src/services/channels/web/controllers/tab.ts index cc341470bf..159286fa1e 100644 --- a/twake/backend/node/src/services/channels/web/controllers/tab.ts +++ b/twake/backend/node/src/services/channels/web/controllers/tab.ts @@ -1,10 +1,9 @@ import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { CrudExeption, Pagination } from "../../../../core/platform/framework/api/crud-service"; +import { CrudException, Pagination } from "../../../../core/platform/framework/api/crud-service"; import { ChannelTab, ChannelTabPrimaryKey } from "../../entities"; -import { TabService } from "../../provider"; import { - ChannelTabParameters, ChannelParameters, + ChannelTabParameters, CreateChannelTabBody, PaginationQueryParameters, UpdateChannelTabBody, @@ -21,9 +20,9 @@ import { ResourceListResponse, ResourceUpdateResponse, } from "../../../../utils/types"; -import { getTabsRealtimeRoom } from "../../services/tab/service"; -import { localEventBus } from "../../../../core/platform/framework/pubsub"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; +import { getTabsRealtimeRoom } from "../../services/tab"; +import gr from "../../../global-resolver"; export class ChannelTabCrudController implements @@ -34,8 +33,6 @@ export class ChannelTabCrudController ResourceDeleteResponse > { - constructor(protected websockets: RealtimeServiceAPI, protected service: TabService) {} - getPrimaryKey(request: FastifyRequest<{ Params: ChannelTabParameters }>): ChannelTabPrimaryKey { return { id: request.params.tab_id, @@ -49,13 +46,13 @@ export class ChannelTabCrudController request: FastifyRequest<{ Params: ChannelTabParameters }>, reply: FastifyReply, ): Promise> { - const resource = await this.service.get( + const resource = await gr.services.tab.get( this.getPrimaryKey(request), getExecutionContext(request), ); if (!resource) { - throw CrudExeption.notFound(`Channel member ${request.params.tab_id} not found`); + throw CrudException.notFound(`Channel member ${request.params.tab_id} not found`); } return { @@ -78,7 +75,7 @@ export class ChannelTabCrudController try { const context = getExecutionContext(request); - const result = await this.service.save(entity, {}, context); + const result = await gr.services.tab.save(entity, {}, context); if (result.entity) { localEventBus.publish("channel:tab:created", { @@ -109,7 +106,7 @@ export class ChannelTabCrudController }); try { - const result = await this.service.save(entity, {}, getExecutionContext(request)); + const result = await gr.services.tab.save(entity, {}, getExecutionContext(request)); if (result.entity) { reply.code(200); @@ -129,7 +126,7 @@ export class ChannelTabCrudController ): Promise { try { const context = getExecutionContext(request); - const deleteResult = await this.service.delete(this.getPrimaryKey(request), context); + const deleteResult = await gr.services.tab.delete(this.getPrimaryKey(request)); if (deleteResult.deleted) { localEventBus.publish("channel:tab:deleted", { @@ -166,7 +163,7 @@ export class ChannelTabCrudController }>, ): Promise> { const context = getExecutionContext(request); - const list = await this.service.list( + const list = await gr.services.tab.list( new Pagination(request.query.page_token, request.query.limit), {}, context, @@ -177,7 +174,7 @@ export class ChannelTabCrudController resources: list.getEntities(), }, ...(request.query.websockets && { - websockets: this.websockets.sign( + websockets: gr.platformServices.realtime.sign( [{ room: getTabsRealtimeRoom(context.channel) }], context.user.id, ), diff --git a/twake/backend/node/src/services/channels/web/index.ts b/twake/backend/node/src/services/channels/web/index.ts index 023eedcb09..2945a147bc 100644 --- a/twake/backend/node/src/services/channels/web/index.ts +++ b/twake/backend/node/src/services/channels/web/index.ts @@ -1,14 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import ChannelServiceAPI from "../provider"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: ChannelServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /internal/services/channels/v1 routes"); diff --git a/twake/backend/node/src/services/channels/web/routes.ts b/twake/backend/node/src/services/channels/web/routes.ts index 18e7366b2f..7cae0645b7 100644 --- a/twake/backend/node/src/services/channels/web/routes.ts +++ b/twake/backend/node/src/services/channels/web/routes.ts @@ -1,5 +1,10 @@ import { FastifyInstance, FastifyPluginCallback } from "fastify"; -import { BaseChannelsParameters, ChannelParameters, PaginationQueryParameters } from "./types"; +import { + BaseChannelsParameters, + ChannelParameters, + PaginationQueryParameters, + RecentChannelsParameters, +} from "./types"; import { createChannelMemberSchema, createChannelSchema, @@ -13,31 +18,25 @@ import { ChannelMemberCrudController, ChannelTabCrudController, } from "./controllers"; -import ChannelServiceAPI from "../provider"; import { checkCompanyAndWorkspaceForUser } from "./middleware"; import { FastifyRequest } from "fastify/types/request"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; +import { checkUserBelongsToCompany } from "../../../utils/company"; const channelsUrl = "/companies/:company_id/workspaces/:workspace_id/channels"; const membersUrl = `${channelsUrl}/:id/members`; const tabsUrl = `${channelsUrl}/:id/tabs`; const pendingEmailsUrl = `${channelsUrl}/:channel_id/pending_emails`; -const routes: FastifyPluginCallback<{ - service: ChannelServiceAPI; - realtime: RealtimeServiceAPI; -}> = (fastify: FastifyInstance, options, next) => { - const channelsController = new ChannelCrudController( - options.realtime, - options.service.channels, - options.service.members, - options.service.pendingEmails, - ); - const membersController = new ChannelMemberCrudController( - options.realtime, - options.service.members, - ); - const tabsController = new ChannelTabCrudController(options.realtime, options.service.tabs); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const channelsController = new ChannelCrudController(); + const membersController = new ChannelMemberCrudController(); + const tabsController = new ChannelTabCrudController(); + + const accessControlCompanyOnly = async ( + request: FastifyRequest<{ Params: RecentChannelsParameters }>, + ) => { + await checkUserBelongsToCompany(request.currentUser.id, request.params.company_id); + }; const accessControl = async (request: FastifyRequest<{ Params: BaseChannelsParameters }>) => { const authorized = await checkCompanyAndWorkspaceForUser( @@ -113,6 +112,21 @@ const routes: FastifyPluginCallback<{ handler: channelsController.updateRead.bind(channelsController), }); + fastify.route({ + method: "GET", + url: "/companies/:company_id/search", + preValidation: [fastify.authenticate], + handler: channelsController.search.bind(channelsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/channels/recent", + preHandler: accessControlCompanyOnly, + preValidation: [fastify.authenticate], + handler: channelsController.recent.bind(channelsController), + }); + // members fastify.route({ @@ -158,6 +172,22 @@ const routes: FastifyPluginCallback<{ handler: membersController.delete.bind(membersController), }); + fastify.route({ + method: "GET", + url: `${membersUrl}/read_sections`, + preHandler: accessControl, + preValidation: [fastify.authenticate], + handler: membersController.getAllChannelMembersReadSections.bind(membersController), + }); + + fastify.route({ + method: "GET", + url: `${membersUrl}/:member_id/read_sections`, + preHandler: accessControl, + preValidation: [fastify.authenticate], + handler: membersController.getChannelMemberReadSections.bind(membersController), + }); + // pending_emails fastify.route({ diff --git a/twake/backend/node/src/services/channels/web/schemas.ts b/twake/backend/node/src/services/channels/web/schemas.ts index 1c557ad335..d5bbb44599 100644 --- a/twake/backend/node/src/services/channels/web/schemas.ts +++ b/twake/backend/node/src/services/channels/web/schemas.ts @@ -39,16 +39,9 @@ const channelSchema = { owner: { type: "string" }, visibility: { type: "string", enum: ["private", "public", "direct"] }, last_activity: { type: "number" }, - user_member: channelMemberSchema, + user_member: {}, direct_channel_members: { type: "array" }, - stats: { - type: "object", - properties: { - members: { type: "number" }, - guests: { type: "number" }, - messages: { type: "number" }, - }, - }, + stats: {}, }, }; diff --git a/twake/backend/node/src/services/channels/web/types.ts b/twake/backend/node/src/services/channels/web/types.ts index 09375d03ef..dad0eabbb6 100644 --- a/twake/backend/node/src/services/channels/web/types.ts +++ b/twake/backend/node/src/services/channels/web/types.ts @@ -2,6 +2,10 @@ import { Channel, ChannelMember, ChannelPendingEmails, ChannelTab } from "../ent export declare type DirectChannel = "direct"; +export interface RecentChannelsParameters { + company_id: string; +} + export interface BaseChannelsParameters { company_id: string; workspace_id: string | DirectChannel; @@ -28,6 +32,10 @@ export interface ChannelListQueryParameters extends PaginationQueryParameters { mine?: boolean; } +export interface ChannelSearchQueryParameters extends PaginationQueryParameters { + q: string; +} + export class CreateChannelBody { options?: ChannelCreateOptions; resource: ChannelCreateResource; @@ -51,6 +59,7 @@ export class ChannelListOptions { channels?: string[]; mine?: boolean; company_role?: string; + user_id?: string; } export class UpdateChannelBody { diff --git a/twake/backend/node/src/services/console/api.ts b/twake/backend/node/src/services/console/api.ts deleted file mode 100644 index 1f1fc53a75..0000000000 --- a/twake/backend/node/src/services/console/api.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { TwakeServiceProvider } from "../../core/platform/framework"; -import { ConsoleOptions, ConsoleType, MergeProgress } from "./types"; -import { ConsoleServiceClient } from "./client-interface"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import UserServiceAPI from "../user/api"; -import User from "../user/entities/user"; - -export interface ConsoleServiceAPI extends TwakeServiceProvider { - merge( - baseUrl: string, - concurrent: number, - dryRun: boolean, - console: string, - link: boolean, - client: string, - secret: string, - ): MergeProgress; - - getClient(): ConsoleServiceClient; - - consoleType: ConsoleType; - consoleOptions: ConsoleOptions; - services: { - database: DatabaseServiceAPI; - userService: UserServiceAPI; - }; - - processPendingUser(user: User): Promise; - - getUserByAccessToken(accessToken: string): User; -} diff --git a/twake/backend/node/src/services/console/client-factory.ts b/twake/backend/node/src/services/console/client-factory.ts index e0b118f85f..839a4d82c9 100644 --- a/twake/backend/node/src/services/console/client-factory.ts +++ b/twake/backend/node/src/services/console/client-factory.ts @@ -1,11 +1,11 @@ import { ConsoleRemoteClient } from "./clients/remote"; import { ConsoleServiceClient } from "./client-interface"; -import { ConsoleOptions, ConsoleType } from "./types"; +import { ConsoleType } from "./types"; import { ConsoleInternalClient } from "./clients/internal"; -import { ConsoleServiceAPI } from "./api"; +import { ConsoleServiceImpl } from "./service"; class StaticConsoleClientFactory { - create(consoleInstance: ConsoleServiceAPI): ConsoleServiceClient { + create(consoleInstance: ConsoleServiceImpl): ConsoleServiceClient { const type: ConsoleType = consoleInstance.consoleType; switch (type) { case "remote": diff --git a/twake/backend/node/src/services/console/client-interface.ts b/twake/backend/node/src/services/console/client-interface.ts index 912cffe4e5..878b90ce04 100644 --- a/twake/backend/node/src/services/console/client-interface.ts +++ b/twake/backend/node/src/services/console/client-interface.ts @@ -2,7 +2,6 @@ import { ConsoleCompany, ConsoleHookCompany, ConsoleHookUser, - ConsoleOptions, CreateConsoleCompany, CreateConsoleUser, CreatedConsoleCompany, @@ -12,9 +11,7 @@ import { UpdatedConsoleUserRole, } from "./types"; import User from "../user/entities/user"; -import Company, { CompanyPrimaryKey, CompanySearchKey } from "../user/entities/company"; -import { CompanyUserRole } from "../user/web/types"; -import { ExternalGroupPrimaryKey } from "../user/entities/external_company"; +import Company, { CompanySearchKey } from "../user/entities/company"; export interface ConsoleServiceClient { /** diff --git a/twake/backend/node/src/services/console/clients/internal.ts b/twake/backend/node/src/services/console/clients/internal.ts index 4368e56c35..e7fc4d382e 100644 --- a/twake/backend/node/src/services/console/clients/internal.ts +++ b/twake/backend/node/src/services/console/clients/internal.ts @@ -1,4 +1,4 @@ -import axios, { AxiosInstance } from "axios"; +import { AxiosInstance } from "axios"; import { merge } from "lodash"; import { ConsoleServiceClient } from "../client-interface"; @@ -6,8 +6,6 @@ import { ConsoleCompany, ConsoleHookCompany, ConsoleHookUser, - ConsoleOptions, - ConsoleUser, CreateConsoleCompany, CreateConsoleUser, CreatedConsoleCompany, @@ -17,28 +15,24 @@ import { } from "../types"; import { v1 as uuidv1 } from "uuid"; -import { ConsoleServiceAPI } from "../api"; import User, { getInstance as getUserInstance } from "../../user/entities/user"; import Company, { CompanySearchKey } from "../../user/entities/company"; -import { CompanyUserRole } from "../../user/web/types"; import { logger } from "../../../core/platform/framework/logger"; +import gr from "../../global-resolver"; +import { ConsoleServiceImpl } from "../service"; export class ConsoleInternalClient implements ConsoleServiceClient { version: "1"; client: AxiosInstance; - constructor(private consoleInstance: ConsoleServiceAPI) {} + constructor(private consoleInstance: ConsoleServiceImpl) {} async addUserToCompany( company: ConsoleCompany, user: CreateConsoleUser, ): Promise { - logger.info(`Internal: addUserToCompany`); - await this.consoleInstance.services.userService.companies.setUserRole( - company.id, - user.id, - user.role, - ); + logger.info("Internal: addUserToCompany"); + await gr.services.companies.setUserRole(company.id, user.id, user.role); return merge(user, { _id: user.id }); } @@ -46,18 +40,17 @@ export class ConsoleInternalClient implements ConsoleServiceClient { company: ConsoleCompany, user: UpdateConsoleUserRole, ): Promise { - logger.info(`Internal: updateUserRole`); + logger.info("Internal: updateUserRole"); throw Error("ConsoleInternalClient.updateUserRole is not implemented"); } async createCompany(company: CreateConsoleCompany): Promise { - logger.info(`Internal: `); + logger.info("Internal: "); throw Error("ConsoleInternalClient.createCompany is not implemented"); } async addUserToTwake(user: CreateConsoleUser): Promise { - logger.info(`Internal: addUserToTwake`); - const usersApi = this.consoleInstance.services.userService.users; + logger.info("Internal: addUserToTwake"); const userToCreate = getUserInstance({ id: uuidv1(), email_canonical: user.email, @@ -65,50 +58,50 @@ export class ConsoleInternalClient implements ConsoleServiceClient { last_name: user.lastName, }); - const createdUser = await usersApi.save(userToCreate).then(result => result.entity); + const createdUser = await gr.services.users.save(userToCreate).then(result => result.entity); if (user.password) { - await usersApi.setPassword({ id: createdUser.id }, user.password); + await gr.services.users.setPassword({ id: createdUser.id }, user.password); } return createdUser; } updateLocalCompanyFromConsole(companyDTO: ConsoleHookCompany): Promise { - logger.info(`Internal: updateLocalCompanyFromConsole`); + logger.info("Internal: updateLocalCompanyFromConsole"); throw new Error("Method should not be implemented."); } updateLocalUserFromConsole(code: string): Promise { - logger.info(`Internal: updateLocalUserFromConsole`); + logger.info("Internal: updateLocalUserFromConsole"); throw new Error("Method should not be implemented."); } removeCompany(companySearchKey: CompanySearchKey): Promise { - logger.info(`Internal: removeCompany`); + logger.info("Internal: removeCompany"); throw new Error("Method should not be implemented."); } removeCompanyUser(consoleUserId: string, company: Company): Promise { - logger.info(`Internal: removeCompanyUser`); + logger.info("Internal: removeCompanyUser"); throw new Error("Method should not be implemented."); } removeUser(consoleUserId: string): Promise { - logger.info(`Internal: removeUser`); + logger.info("Internal: removeUser"); throw new Error("Method should not be implemented."); } fetchCompanyInfo(consoleCompanyCode: string): Promise { - logger.info(`Internal: fetchCompanyInfo`); + logger.info("Internal: fetchCompanyInfo"); throw new Error("Method should not be implemented."); } getUserByAccessToken(accessToken: string): Promise { - logger.info(`Internal: getUserByAccessToken`); + logger.info("Internal: getUserByAccessToken"); throw new Error("Method should not be implemented."); } resendVerificationEmail(accessToken: string): Promise { - logger.info(`Internal: resendVerificationEmail`); + logger.info("Internal: resendVerificationEmail"); throw new Error("Method should not be implemented."); } } diff --git a/twake/backend/node/src/services/console/clients/remote.ts b/twake/backend/node/src/services/console/clients/remote.ts index bab92a765d..af40754d2a 100644 --- a/twake/backend/node/src/services/console/clients/remote.ts +++ b/twake/backend/node/src/services/console/clients/remote.ts @@ -15,28 +15,27 @@ import { } from "../types"; import User, { getInstance } from "../../user/entities/user"; -import { ConsoleServiceAPI } from "../api"; import Company, { CompanySearchKey, getInstance as getCompanyInstance, } from "../../user/entities/company"; -import { CrudExeption } from "../../../core/platform/framework/api/crud-service"; -import UserServiceAPI from "../../user/api"; +import { CrudException } from "../../../core/platform/framework/api/crud-service"; import coalesce from "../../../utils/coalesce"; import { logger } from "../../../core/platform/framework/logger"; import _ from "lodash"; +import { CompanyFeaturesEnum, CompanyLimitsEnum } from "../../user/web/types"; +import gr from "../../global-resolver"; +import { ConsoleServiceImpl } from "../service"; export class ConsoleRemoteClient implements ConsoleServiceClient { version: "1"; client: AxiosInstance; private infos: ConsoleOptions; - private userService: UserServiceAPI; - constructor(consoleInstance: ConsoleServiceAPI, private dryRun: boolean) { + constructor(consoleInstance: ConsoleServiceImpl, private dryRun: boolean) { this.infos = consoleInstance.consoleOptions; this.client = axios.create({ baseURL: this.infos.url }); - this.userService = consoleInstance.services.userService; } private auth() { @@ -49,13 +48,15 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { ): Promise { logger.info("Remote: addUserToCompany"); + const isNewConsole = this.infos.new_console; + if (this.dryRun) { return { _id: uuidv1(), }; } - if (user.skipInvite) { + if (user.skipInvite && user.name && user.email && user.password) { return this.client .post(`/api/companies/${company.code}/users`, user, { auth: this.auth(), @@ -77,16 +78,43 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { }, ], inviter: { email: user.inviterEmail }, + ...(isNewConsole + ? { + applicationCodes: ["twake"], + } + : {}), }; const result = await this.client - .post(`/api/companies/${company.code}/users/invitation`, invitationData, { - auth: this.auth(), - headers: { - "Content-Type": "application/json", + .post( + `/api/companies/${company.code}/${isNewConsole ? "invitations" : "users/invitation"}`, + invitationData, + { + auth: this.auth(), + headers: { + "Content-Type": "application/json", + }, }, - }) - .then(({ data }) => data); + ) + .then(async ({ data, status }) => { + //Fixme: When console solve https://gitlab.com/COMPANY_LINAGORA/software/saas/twake-console-account/-/issues/36 + // we can remove this fallback + if ([200, 201].indexOf(status) >= 0) { + return data; + } else { + return this.client + .post(`/api/companies/${company.code}/users`, user, { + auth: this.auth(), + headers: { + "Content-Type": "application/json", + }, + params: { + skipInvite: user.skipInvite, + }, + }) + .then(({ data }) => data); + } + }); return result; } @@ -152,7 +180,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { const companyDTO = await this.fetchCompanyInfo(partialCompanyDTO.details.code); - let company = await this.userService.companies.getCompany({ + let company = await gr.services.companies.getCompany({ identity_provider_id: companyDTO.details.code, }); @@ -162,7 +190,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { identity_provider: "console", identity_provider_id: companyDTO.details.code, }); - company = await this.userService.companies.createCompany(newCompany); + company = await gr.services.companies.createCompany(newCompany); } const details = companyDTO.details; @@ -181,36 +209,43 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { } if (!company.plan) { - company.plan = { name: "", features: {} }; + company.plan = { name: "", limits: undefined, features: undefined }; } + const limits = companyDTO.limits.twake || companyDTO.limits; + //FIXME this is a hack right now! let planFeatures: any = { - "chat:guests": true, - "chat:message_history": true, - "chat:multiple_workspaces": true, - "chat:edit_files": true, - "chat:unlimited_storage": true, + [CompanyFeaturesEnum.CHAT_GUESTS]: true, + [CompanyFeaturesEnum.CHAT_MESSAGE_HISTORY]: true, + [CompanyFeaturesEnum.CHAT_MULTIPLE_WORKSPACES]: true, + [CompanyFeaturesEnum.CHAT_EDIT_FILES]: true, + [CompanyFeaturesEnum.CHAT_UNLIMITED_STORAGE]: true, + [CompanyFeaturesEnum.COMPANY_INVITE_MEMBER]: true, }; - if (companyDTO.limits.members < 0 && this.infos.type === "remote") { + + if (limits.members < 0 && this.infos.type === "remote") { //Hack to say this is free version planFeatures = { - "chat:guests": false, - "chat:message_history": false, - "chat:message_history_limit": 10000, - "chat:multiple_workspaces": false, - "chat:edit_files": false, - "chat:unlimited_storage": false, //Currently inactive + [CompanyFeaturesEnum.CHAT_GUESTS]: false, + [CompanyFeaturesEnum.CHAT_MESSAGE_HISTORY]: false, + [CompanyFeaturesEnum.CHAT_MULTIPLE_WORKSPACES]: false, + [CompanyFeaturesEnum.CHAT_EDIT_FILES]: false, + [CompanyFeaturesEnum.CHAT_UNLIMITED_STORAGE]: false, // Currently inactive }; company.plan.name = "free"; } else { company.plan.name = "standard"; } - company.plan.features = { ...planFeatures, ...companyDTO.limits }; + company.plan.features = { ...planFeatures }; + company.plan.limits = { + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]: 10000, // To remove duplicata since we define this in formatCompany function + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]: limits["members"], + }; company.stats = coalesce(companyDTO.stats, company.stats); - await this.userService.companies.updateCompany(company); + await gr.services.companies.updateCompany(company); return company; } @@ -221,16 +256,18 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { const userDTO = await this.fetchUserInfo(code); if (!userDTO) { - throw CrudExeption.badRequest("User not found on Console"); + throw CrudException.badRequest("User not found on Console"); } - const roles = userDTO.roles; + const roles = userDTO.roles.filter( + role => role.applications === undefined || role.applications.find(a => a.code === "twake"), + ); - let user = await this.userService.users.getByConsoleId(userDTO._id); + let user = await gr.services.users.getByConsoleId(userDTO._id); if (!user) { if (!userDTO.email) { - throw CrudExeption.badRequest("Email is required"); + throw CrudException.badRequest("Email is required"); } let username = userDTO.email @@ -239,17 +276,39 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { .replace(/[^a-zA-Z0-9]/g, "") .replace(/ +/g, "_"); - if (await this.userService.users.isEmailAlreadyInUse(userDTO.email)) { - throw CrudExeption.badRequest("Console user not created because email already exists"); + if (await gr.services.users.isEmailAlreadyInUse(userDTO.email)) { + const user = await gr.services.users.getByEmail(userDTO.email); + + if (user.identity_provider === "console") { + let emailUserOnConsole = null; + try { + emailUserOnConsole = await this.fetchUserInfo(user.identity_provider_id); + } catch (err) {} + if (emailUserOnConsole?._id) { + throw CrudException.badRequest( + `Console user not created because email already exists on console with different id: ${emailUserOnConsole._id} while requested to provision user with id: ${userDTO._id}`, + ); + } + + //If not present on console, then anonymise this one and create a new one + await gr.services.users.anonymizeAndDelete( + { id: user.id }, + { + user: { id: user.id, server_request: true }, + }, + ); + + //Now we can create the new user + } } - username = await this.userService.users.getAvailableUsername(username); + username = await gr.services.users.getAvailableUsername(username); if (!username) { - throw CrudExeption.badRequest("Console user not created because username already exists"); + throw CrudException.badRequest("Console user not created because username already exists"); } user = getInstance({}); - user.username_canonical = username; + user.username_canonical = (username || "").toLocaleLowerCase(); user.email_canonical = userDTO.email; user.deleted = false; } @@ -278,51 +337,52 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { ? this.infos.url.replace(/\/$/, "") + "/api/avatars/" + avatar.value : ""; - await this.userService.users.save(user); + await gr.services.users.save(user); const getCompanyByCode = async (companyCode: string) => { - let company = await this.userService.companies.getCompany({ + let company = await gr.services.companies.getCompany({ identity_provider_id: companyCode, }); if (!company) { const companyDTO = await this.fetchCompanyInfo(companyCode); await this.updateLocalCompanyFromConsole(companyDTO); - company = await this.userService.companies.getCompany({ + company = await gr.services.companies.getCompany({ identity_provider_id: companyCode, }); } return company; }; - const companies = []; - if (userDTO.roles) { + const updatedListOfCompanies = []; + if (roles) { for (const role of roles) { const companyConsoleCode = role.targetCode; const roleName = role.roleCode; const company = await getCompanyByCode(companyConsoleCode); if (!company) { - throw CrudExeption.notFound(`Company ${companyConsoleCode} not found`); + throw CrudException.notFound(`Company ${companyConsoleCode} not found`); } //Make sure user is active, if not we remove it if (role.status !== "deactivated") { - companies.push(company); - await this.userService.companies.setUserRole(company.id, user.id, roleName); + updatedListOfCompanies.push(company); + const applications = (role.applications || []).map(a => a.code); + await gr.services.companies.setUserRole(company.id, user.id, roleName, applications); } } } // Remove user from companies not in the console - const currentCompanies = await this.userService.companies.getAllForUser(user.id); + const currentCompanies = await gr.services.companies.getAllForUser(user.id); for (const company of currentCompanies) { - if (!companies.map(c => c.id).includes(company.group_id)) { - await this.userService.companies.removeUserFromCompany( + if (!updatedListOfCompanies.map(c => c.id).includes(company.group_id)) { + await gr.services.companies.removeUserFromCompany( { id: company.group_id }, { id: user.id }, ); } } - await this.userService.users.save(user, {}, { user: { id: user.id, server_request: true } }); + await gr.services.users.save(user, { user: { id: user.id, server_request: true } }); return user; } @@ -330,23 +390,23 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { async removeCompanyUser(consoleUserId: string, company: Company): Promise { logger.info("Remote: removeCompanyUser"); - const user = await this.userService.users.getByConsoleId(consoleUserId); + const user = await gr.services.users.getByConsoleId(consoleUserId); if (!user) { - throw CrudExeption.notFound(`User ${consoleUserId} doesn't exists`); + throw CrudException.notFound(`User ${consoleUserId} doesn't exists`); } - await this.userService.companies.removeUserFromCompany({ id: company.id }, { id: user.id }); + await gr.services.companies.removeUserFromCompany({ id: company.id }, { id: user.id }); } async removeUser(consoleUserId: string): Promise { logger.info("Remote: removeUser"); - const user = await this.userService.users.getByConsoleId(consoleUserId); + const user = await gr.services.users.getByConsoleId(consoleUserId); if (!user) { throw new Error("User does not exists on Twake."); } - await this.userService.users.anonymizeAndDelete( + await gr.services.users.anonymizeAndDelete( { id: user.id }, { user: { id: user.id, server_request: true }, @@ -356,7 +416,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { async removeCompany(companySearchKey: CompanySearchKey): Promise { logger.info("Remote: removeCompany"); - await this.userService.companies.removeCompany(companySearchKey); + await gr.services.companies.removeCompany(companySearchKey); } fetchCompanyInfo(consoleCompanyCode: string): Promise { @@ -371,7 +431,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { .then(({ data }) => data.company) .catch(e => { if (e.response.status === 401) { - throw CrudExeption.forbidden("Bad console credentials"); + throw CrudException.forbidden("Bad console credentials"); } throw e; }); @@ -389,7 +449,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { .then(({ data }) => data) .catch(e => { if (e.response.status === 401) { - throw CrudExeption.forbidden("Bad console credentials"); + throw CrudException.forbidden("Bad console credentials"); } throw e; }); @@ -407,7 +467,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { .then(({ data }) => data) .catch(e => { if (e.response?.status === 401) { - throw CrudExeption.forbidden("Bad access token credentials"); + throw CrudException.forbidden("Bad access token credentials"); } throw e; }); @@ -431,7 +491,7 @@ export class ConsoleRemoteClient implements ConsoleServiceClient { .then(({ data }) => data) .catch(e => { if (e.response.status === 401) { - throw CrudExeption.forbidden("Bad credentials"); + throw CrudException.forbidden("Bad credentials"); } throw e; }); diff --git a/twake/backend/node/src/services/console/index.ts b/twake/backend/node/src/services/console/index.ts index 2da4446ac0..43eac0d2f1 100644 --- a/twake/backend/node/src/services/console/index.ts +++ b/twake/backend/node/src/services/console/index.ts @@ -1,56 +1,23 @@ -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import { Consumes, Prefix, TwakeService } from "../../core/platform/framework"; -import UserServiceAPI from "../user/api"; -import { ConsoleServiceAPI } from "./api"; -import { getService } from "./service"; -import { ConsoleOptions, ConsoleType } from "./types"; -import web from "./web/index"; +import { Prefix, TwakeService } from "../../core/platform/framework"; import WebServerAPI from "../../core/platform/services/webserver/provider"; -import AuthServiceAPI from "../../core/platform/services/auth/provider"; +import web from "./web"; @Prefix("/internal/services/console/v1") -@Consumes(["user", "database", "auth"]) -export default class ConsoleService extends TwakeService { +export default class ConsoleService extends TwakeService { version = "1"; name = "console"; - private service: ConsoleServiceAPI; - - async doInit(): Promise { - const type = this.configuration.get("type"); - const options: ConsoleOptions = { ...this.configuration.get(type), type }; - - this.service = getService( - this.context.getProvider("database"), - this.context.getProvider("user"), - type, - options, - ); + public async doInit(): Promise { const fastify = this.context.getProvider("webserver").getServer(); - - const authService = this.context.getProvider("auth"); - const userService = this.context.getProvider("user"); - this.service.services.userService = userService; - fastify.register((instance, _opts, next) => { - web(instance, { - prefix: this.prefix, - service: this.service, - authService: authService, - userService: userService, - options, - }); + web(instance, { prefix: this.prefix }); next(); }); - - return this; - } - - async doStart(): Promise { return this; } - api(): ConsoleServiceAPI { - return this.service; + // TODO: remove + api(): undefined { + return undefined; } } diff --git a/twake/backend/node/src/services/console/processing/merge.ts b/twake/backend/node/src/services/console/processing/merge.ts index 0039beaf58..62fe231612 100644 --- a/twake/backend/node/src/services/console/processing/merge.ts +++ b/twake/backend/node/src/services/console/processing/merge.ts @@ -13,15 +13,17 @@ import { toArray, } from "rxjs/operators"; import { getLogger } from "../../../core/platform/framework"; -import { Paginable } from "../../../core/platform/framework/api/crud-service"; +import { + ExecutionContext, + Paginable, + Pagination, +} from "../../../core/platform/framework/api/crud-service"; import Company from "../../user/entities/company"; import User from "../../user/entities/user"; -import UserServiceAPI from "../../user/api"; import { CompanyCreatedStreamObject, CompanyReport, ConsoleOptions, - ConsoleType, CreatedConsoleCompany, CreatedConsoleUser, MergeProgress, @@ -37,8 +39,8 @@ import { ConsoleRemoteClient } from "../clients/remote"; import { ConsoleServiceClient } from "../client-interface"; import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; import { CompanyUserRole } from "../../user/web/types"; -import { ConsoleServiceAPI } from "../api"; -import { getService as getConsoleService } from "../service"; +import gr from "../../global-resolver"; +import { ConsoleServiceImpl } from "../service"; const logger = getLogger("console.process.merge"); @@ -47,14 +49,12 @@ export class MergeProcess { constructor( private database: DatabaseServiceAPI, - private userService: UserServiceAPI, private dryRun: boolean, private consoleId: string = "console", private linkExternal: boolean = true, consoleClientOptions: ConsoleOptions, ) { - const consoleService = getConsoleService(null, null, "remote", consoleClientOptions); - + const consoleService = new ConsoleServiceImpl(consoleClientOptions); this.client = new ConsoleRemoteClient(consoleService, dryRun); } @@ -173,6 +173,7 @@ export class MergeProcess { private getStreams( concurrent: number = 1, + context?: ExecutionContext, ): { // hot companies observable companies$: Observable; @@ -196,7 +197,7 @@ export class MergeProcess { ), ), mergeMap( - userInCompany => this.createUser(userInCompany.company.source, userInCompany.user), + userInCompany => this.createUser(userInCompany.company.source, userInCompany.user, context), concurrent, ), // make it hot @@ -210,7 +211,13 @@ export class MergeProcess { } private getUserIds(company: Company, paginable?: Paginable): Observable { - return from(this.userService.companies.getUsers({ group_id: company.id }, paginable)).pipe( + const pagination = new Pagination( + paginable?.page_token, + paginable?.limitStr, + paginable?.reversed, + ); + + return from(gr.services.companies.getUsers({ group_id: company.id }, pagination)).pipe( mergeMap(companyUsers => { const items$ = from(companyUsers.getEntities()); const next$ = companyUsers?.nextPage?.page_token @@ -223,7 +230,7 @@ export class MergeProcess { } private getCompanies(paginable?: Paginable): Observable { - return from(this.userService.companies.getCompanies(paginable)).pipe( + return from(gr.services.companies.getCompanies(paginable)).pipe( mergeMap(companiesResult => { const items$ = from(companiesResult.getEntities()); const next$ = companiesResult?.nextPage?.page_token @@ -272,13 +279,14 @@ export class MergeProcess { private async createUser( company: Company, companyUser: CompanyUser, + context: ExecutionContext, ): Promise { logger.debug("Creating user in console %o", companyUser.user_id); let error: Error; let result: CreatedConsoleUser; try { - const user = await this.userService.users.get({ id: companyUser.user_id }); + const user = await gr.services.users.get({ id: companyUser.user_id }); if (!user) { throw new Error(`User ${companyUser.user_id} not found`); @@ -296,7 +304,7 @@ export class MergeProcess { if (companyUser.isExterne) { role = "guest"; } - const workspacesUsers = await this.userService.workspaces.getAllForUser( + const workspacesUsers = await gr.services.workspaces.getAllForUser( { userId: companyUser.user_id }, { id: company.id }, ); @@ -325,6 +333,7 @@ export class MergeProcess { }), skipInvite: true, role, + inviterEmail: "", }, ); @@ -333,7 +342,7 @@ export class MergeProcess { CompanyUser, ); companyUser.role = role; - await companyUserRepository.save(companyUser); + await companyUserRepository.save(companyUser, context); if (this.linkExternal) { await this.createUserLink(user, result, this.consoleId); @@ -363,7 +372,7 @@ export class MergeProcess { return; } - await this.userService.external.createExternalUser( + await gr.services.externalUser.createExternalUser( getExternalUserInstance({ service_id: serviceId, external_id: remoteUser._id, @@ -381,7 +390,7 @@ export class MergeProcess { return; } - await this.userService.external.createExternalGroup( + await gr.services.externalUser.createExternalGroup( getExternalGroupInstance({ service_id: serviceId, company_id: localCompany.id, diff --git a/twake/backend/node/src/services/console/service.ts b/twake/backend/node/src/services/console/service.ts index 7067607b74..11793b8018 100644 --- a/twake/backend/node/src/services/console/service.ts +++ b/twake/backend/node/src/services/console/service.ts @@ -1,38 +1,53 @@ import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import UserServiceAPI from "../user/api"; -import { ConsoleServiceAPI } from "./api"; import { MergeProcess } from "./processing/merge"; import { ConsoleOptions, ConsoleType, MergeProgress } from "./types"; import { ConsoleServiceClient } from "./client-interface"; import { ConsoleClientFactory } from "./client-factory"; import User from "../user/entities/user"; +import gr from "../global-resolver"; +import { Configuration, TwakeServiceProvider } from "../../core/platform/framework"; +import assert from "assert"; +import { ExecutionContext } from "../../core/platform/framework/api/crud-service"; -class ConsoleService implements ConsoleServiceAPI { +export class ConsoleServiceImpl implements TwakeServiceProvider { version: "1"; consoleType: ConsoleType; consoleOptions: ConsoleOptions; services: { database: DatabaseServiceAPI; - userService: UserServiceAPI; }; + private configuration: Configuration; - constructor( - database: DatabaseServiceAPI, - userService: UserServiceAPI, - type: ConsoleType, - options: ConsoleOptions, - ) { - this.consoleType = type; + constructor(options?: ConsoleOptions) { this.consoleOptions = options; - this.services = { - database, - userService, - }; } - getUserByAccessToken(accessToken: string): User { - throw new Error("Method not implemented."); + async init(): Promise { + this.configuration = new Configuration("console"); + assert(this.configuration, "console configuration is missing"); + const type = this.configuration.get("type") as ConsoleType; + assert(type, "console configuration type is not defined"); + + const s = this.configuration.get(type) as ConsoleOptions; + + this.consoleOptions = { + type: type, + new_console: s.new_console, + username: s.username, + password: s.password, + url: s.url, + hook: { + token: s.hook?.token, + public_key: s.hook?.public_key, + }, + disable_account_creation: s.disable_account_creation, + }; + + this.consoleOptions.type = type; + this.consoleType = type; + + return this; } merge( @@ -43,36 +58,21 @@ class ConsoleService implements ConsoleServiceAPI { link: boolean = true, client: string, secret: string, + context?: ExecutionContext, ): MergeProgress { - return new MergeProcess( - this.services.database, - this.services.userService, - dryRun, - console, - link, - { - username: client, - password: secret, - url: baseUrl, - } as ConsoleOptions, - ).merge(concurrent); + return new MergeProcess(this.services.database, dryRun, console, link, { + type: "remote", + username: client, + password: secret, + url: baseUrl, + } as ConsoleOptions).merge(concurrent); } getClient(): ConsoleServiceClient { return ConsoleClientFactory.create(this); } - async processPendingUser(user: User): Promise { - const services = this.services.userService; - await services.workspaces.processPendingUser(user); + async processPendingUser(user: User, context?: ExecutionContext): Promise { + await gr.services.workspaces.processPendingUser(user, null, context); } } - -export function getService( - database: DatabaseServiceAPI, - userService: UserServiceAPI, - type: ConsoleType, - options: ConsoleOptions, -): ConsoleServiceAPI { - return new ConsoleService(database, userService, type, options); -} diff --git a/twake/backend/node/src/services/console/types.ts b/twake/backend/node/src/services/console/types.ts index 0cc89c2aa7..547f9e6750 100644 --- a/twake/backend/node/src/services/console/types.ts +++ b/twake/backend/node/src/services/console/types.ts @@ -20,9 +20,13 @@ export interface CreateConsoleCompany { applications?: string[]; planId?: string; limits?: { - members: number; - guests: number; - storage: number; + members?: number; //Old console version + guests?: number; //Old console version + twake: { + members: number; + guests: number; + storage: number; + }; }; } @@ -41,7 +45,7 @@ export interface CreateConsoleUser { password: string; role: CompanyUserRole; skipInvite: boolean; - inviterEmail?: string; + inviterEmail: string; } export interface CreateInternalUser { @@ -121,7 +125,8 @@ export type ProcessReport = { export type ConsoleType = "remote" | "internal"; export type ConsoleOptions = { - type: "remote" | "internal"; + type: ConsoleType; + new_console: boolean; username: string; password: string; url: string; @@ -134,7 +139,15 @@ export type ConsoleOptions = { export type ConsoleHookCompany = { stats: string; - limits: any; + limits: { + members?: number; //Old console version + guests?: number; //Old console version + twake: { + members: number; + guests: number; + storage: number; + }; + }; value: string; details: { code: string; @@ -151,7 +164,16 @@ export type ConsoleHookCompany = { export type ConsoleHookUser = { _id: string; - roles: [{ targetCode: string; roleCode: CompanyUserRole; status: "active" | "deactivated" }]; + roles: [ + { + targetCode: string; + roleCode: CompanyUserRole; + status: "active" | "deactivated"; + applications: { + code: "twake"; + }[]; + }, + ]; email: string; name: string; surname: string; @@ -172,6 +194,10 @@ export type ConsoleHookBodyContent = { user: ConsoleHookUser; }; +export type ConsoleHookCompanyDeletedContent = { + companyCode: string; +}; + export type ConsoleHookPreferenceContent = { preference: { targetCode: string; @@ -180,7 +206,11 @@ export type ConsoleHookPreferenceContent = { export type ConsoleHookBody = { type: string; - content: ConsoleHookBodyContent | ConsoleHookUser | ConsoleHookCompany; + content: + | ConsoleHookBodyContent + | ConsoleHookUser + | ConsoleHookCompany + | ConsoleHookCompanyDeletedContent; signature: string; secret_key?: string; }; diff --git a/twake/backend/node/src/services/console/web/controller.ts b/twake/backend/node/src/services/console/web/controller.ts index d6c8dc0b78..d794dc3444 100644 --- a/twake/backend/node/src/services/console/web/controller.ts +++ b/twake/backend/node/src/services/console/web/controller.ts @@ -1,4 +1,3 @@ -import { ConsoleServiceAPI } from "../api"; import { FastifyReply, FastifyRequest } from "fastify"; import { AuthRequest, @@ -6,32 +5,28 @@ import { ConsoleHookBody, ConsoleHookBodyContent, ConsoleHookCompany, + ConsoleHookCompanyDeletedContent, ConsoleHookPreferenceContent, ConsoleHookResponse, ConsoleHookUser, - ConsoleOptions, + ConsoleType, } from "../types"; import Company from "../../user/entities/company"; -import { CrudExeption } from "../../../core/platform/framework/api/crud-service"; +import { CrudException } from "../../../core/platform/framework/api/crud-service"; import PasswordEncoder from "../../../utils/password-encoder"; import { AccessToken } from "../../../utils/types"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; -import UserServiceAPI from "../../user/api"; import assert from "assert"; -import { logger } from "../../../core/platform/framework/logger"; -import { getInstance } from "../../../services/user/entities/user"; +import { logger } from "../../../core/platform/framework"; +import { getInstance } from "../../user/entities/user"; import { getInstance as getCompanyInstance } from "../../../services/user/entities/company"; import Workspace from "../../../services/workspaces/entities/workspace"; +import gr from "../../global-resolver"; +import { Configuration } from "../../../core/platform/framework"; export class ConsoleController { private passwordEncoder: PasswordEncoder; - constructor( - protected consoleService: ConsoleServiceAPI, - protected authService: AuthServiceAPI, - protected userService: UserServiceAPI, - protected options: ConsoleOptions, - ) { + constructor() { this.passwordEncoder = new PasswordEncoder(); } @@ -41,7 +36,7 @@ export class ConsoleController { } else if (request.body.email && request.body.password) { return { access_token: await this.authByPassword(request.body.email, request.body.password) }; } else { - throw CrudExeption.badRequest("remote_access_token or email+password are required"); + throw CrudException.badRequest("remote_access_token or email+password are required"); } } @@ -50,20 +45,23 @@ export class ConsoleController { Body: { email: string; password: string; first_name: string; last_name: string }; }>, ): Promise { + const configuration = new Configuration("console"); + const type = configuration.get("type") as ConsoleType; + try { //Allow only if no console is set up in this case everyone will be in the same company //Console is set up - if (this.options.type !== "internal") { + if (type !== "internal") { throw new Error("Unable to signup in console mode"); } //Allow only if signup isn't disabled - if (this.options.disable_account_creation) { + if (configuration.get("disable_account_creation")) { throw new Error("Account creation is disabled"); } const email = request.body.email.trim().toLocaleLowerCase(); - if (await this.userService.users.getByEmail(email)) { + if (await gr.services.users.getByEmail(email)) { throw new Error("This email is already used"); } @@ -72,33 +70,33 @@ export class ConsoleController { first_name: request.body.first_name, last_name: request.body.last_name, email_canonical: email, - username_canonical: email.replace("@", "."), + username_canonical: (email.replace("@", ".") || "").toLocaleLowerCase(), }); - const user = await this.userService.users.create(newUser); - await this.userService.users.setPassword({ id: user.entity.id }, request.body.password); + const user = await gr.services.users.create(newUser); + await gr.services.users.setPassword({ id: user.entity.id }, request.body.password); //Create a global company for all users in local mode - const companies = await this.userService.companies.getCompanies(); + const companies = await gr.services.companies.getCompanies(); let company = companies.getEntities()?.[0]; if (!company) { const newCompany = getCompanyInstance({ name: "Twake", - plan: { name: "Local", features: {} }, + plan: { name: "Local", limits: undefined, features: undefined }, }); - company = await this.userService.companies.createCompany(newCompany); + company = await gr.services.companies.createCompany(newCompany); } - await this.userService.companies.setUserRole(company.id, user.entity.id, "admin"); + await gr.services.companies.setUserRole(company.id, user.entity.id, "admin"); //In case someone invited us to a workspace - await this.userService.workspaces.processPendingUser(user.entity); + await gr.services.workspaces.processPendingUser(user.entity); //If user is in no workspace, then we create one for they - const workspaces = await this.userService.workspaces.getAllForUser( + const workspaces = await gr.services.workspaces.getAllForUser( { userId: user.entity.id }, { id: company.id }, ); if (workspaces.length === 0) { - this.userService.workspaces.create( + gr.services.workspaces.create( { company_id: company.id, name: `${ @@ -122,7 +120,7 @@ export class ConsoleController { async tokenRenewal(request: FastifyRequest): Promise { return { - access_token: this.authService.generateJWT( + access_token: gr.platformServices.auth.generateJWT( request.currentUser.id, request.currentUser.email, { @@ -136,9 +134,9 @@ export class ConsoleController { async resendVerificationEmail( request: FastifyRequest, ): Promise<{ success: boolean; email: string }> { - const user = await this.userService.users.get({ id: request.currentUser.id }); + const user = await gr.services.users.get({ id: request.currentUser.id }); - await this.consoleService.getClient().resendVerificationEmail(user.email_canonical); + await gr.services.console.getClient().resendVerificationEmail(user.email_canonical); return { success: true, @@ -147,9 +145,9 @@ export class ConsoleController { } private async getCompanyDataFromConsole( - company: ConsoleHookCompany | ConsoleHookCompany["details"], + company: ConsoleHookCompany | ConsoleHookCompany["details"] | { code: string }, ): Promise { - return this.consoleService + return gr.services.console .getClient() .fetchCompanyInfo( (company as ConsoleHookCompany["details"])?.code || @@ -159,7 +157,7 @@ export class ConsoleController { private async updateCompany(company: ConsoleHookCompany): Promise { const companyDTO = await this.getCompanyDataFromConsole(company); - return this.consoleService.getClient().updateLocalCompanyFromConsole(companyDTO); + return gr.services.console.getClient().updateLocalCompanyFromConsole(companyDTO); } async hook( @@ -195,15 +193,20 @@ export class ConsoleController { await this.planUpdated(request.body.content as ConsoleHookBodyContent); break; case "company_deleted": - await this.companyRemoved(request.body.content as ConsoleHookBodyContent); + await this.companyRemoved(request.body.content as ConsoleHookCompanyDeletedContent); break; case "company_created": + await this.companyUpdated(request.body.content as ConsoleHookBodyContent); + if ((request.body.content as ConsoleHookBodyContent)?.user?._id) { + await this.userUpdated((request.body.content as ConsoleHookBodyContent).user._id); + } + break; case "company_updated": await this.companyUpdated(request.body.content as ConsoleHookBodyContent); break; default: logger.info("Event not recognized"); - throw CrudExeption.notImplemented("Unimplemented"); + throw CrudException.notImplemented("Unimplemented"); } } catch (e) { reply.status(400); @@ -219,32 +222,31 @@ export class ConsoleController { private async userAdded(content: ConsoleHookBodyContent): Promise { const userDTO = content.user; - const user = await this.consoleService.getClient().updateLocalUserFromConsole(userDTO._id); - await this.consoleService.processPendingUser(user); + const user = await gr.services.console.getClient().updateLocalUserFromConsole(userDTO._id); + await this.updateCompany(content.company); + await gr.services.console.processPendingUser(user); } private async userDisabled(content: ConsoleHookBodyContent): Promise { const company = await this.updateCompany(content.company); - await this.consoleService.getClient().removeCompanyUser(content.user._id, company); + await gr.services.console.getClient().removeCompanyUser(content.user._id, company); } private async userRemoved(content: ConsoleHookUser): Promise { - await this.consoleService.getClient().removeUser(content._id); + await gr.services.console.getClient().removeUser(content._id); } private async userUpdated(code: string) { - const user = await this.consoleService.getClient().updateLocalUserFromConsole(code); - await this.consoleService.processPendingUser(user); + const user = await gr.services.console.getClient().updateLocalUserFromConsole(code); + await gr.services.console.processPendingUser(user); } - private async companyRemoved(content: ConsoleHookBodyContent) { - assert(content.company, "content.company is missing"); - assert(content.company.details, "content.company.details is missing"); - assert(content.company.details.code, "content.company.details.code is missing"); + private async companyRemoved(content: ConsoleHookCompanyDeletedContent) { + assert(content.companyCode, "content.companyCode is missing"); - await this.consoleService.getClient().removeCompany({ + await gr.services.console.getClient().removeCompany({ identity_provider: "console", - identity_provider_id: content.company.details.code, + identity_provider_id: content.companyCode, }); } @@ -257,38 +259,38 @@ export class ConsoleController { } private async authByPassword(email: string, password: string): Promise { - const user = await this.userService.users.getByEmail(email); + const user = await gr.services.users.getByEmail(email); if (!user) { - throw CrudExeption.forbidden("User doesn't exists"); + throw CrudException.forbidden("User doesn't exists"); } // allow to login in development mode with any password. This can be used to test without the console provider because the password is not stored locally... if (process.env.NODE_ENV !== "development") { - const [storedPassword, salt] = await this.userService.users.getHashedPassword({ + const [storedPassword, salt] = await gr.services.users.getHashedPassword({ id: user.id, }); if (!(await this.passwordEncoder.isPasswordValid(storedPassword, password, salt))) { - throw CrudExeption.forbidden("Password doesn't match"); + throw CrudException.forbidden("Password doesn't match"); } } else if (process.env.NODE_ENV === "development") { logger.warn("ERROR_NOTONPROD: YOU ARE RUNNING IN DEVELOPMENT MODE, AUTH IS DISABLED!!!"); } - return this.authService.generateJWT(user.id, user.email_canonical, { + return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, { track: user?.preferences?.allow_tracking || false, provider_id: user.identity_provider_id, }); } private async authByToken(accessToken: string): Promise { - const client = this.consoleService.getClient(); + const client = gr.services.console.getClient(); const userDTO = await client.getUserByAccessToken(accessToken); const user = await client.updateLocalUserFromConsole(userDTO._id); if (!user) { - throw CrudExeption.notFound(`User details not found for access token ${accessToken}`); + throw CrudException.notFound(`User details not found for access token ${accessToken}`); } - return this.authService.generateJWT(user.id, user.email_canonical, { + return gr.platformServices.auth.generateJWT(user.id, user.email_canonical, { track: user?.preferences?.allow_tracking || false, provider_id: user.identity_provider_id, }); diff --git a/twake/backend/node/src/services/console/web/index.ts b/twake/backend/node/src/services/console/web/index.ts index 44096a60d2..1fe80a8f86 100644 --- a/twake/backend/node/src/services/console/web/index.ts +++ b/twake/backend/node/src/services/console/web/index.ts @@ -1,18 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { ConsoleServiceAPI } from "../api"; import routes from "./routes"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; -import UserServiceAPI from "../../user/api"; -import { ConsoleOptions } from "../types"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: ConsoleServiceAPI; - authService: AuthServiceAPI; - userService: UserServiceAPI; - options: ConsoleOptions; }>, ): void => { fastify.log.debug("Configuring /console routes"); diff --git a/twake/backend/node/src/services/console/web/routes.ts b/twake/backend/node/src/services/console/web/routes.ts index 822903ae5b..a14a19a70f 100644 --- a/twake/backend/node/src/services/console/web/routes.ts +++ b/twake/backend/node/src/services/console/web/routes.ts @@ -1,44 +1,31 @@ import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify"; import { authenticationSchema, consoleHookSchema, tokenRenewalSchema } from "./schemas"; import crypto from "crypto"; - -import { ConsoleServiceAPI } from "../api"; // import { WorkspaceBaseRequest, WorkspaceUsersBaseRequest, WorkspaceUsersRequest } from "./types"; import { ConsoleController } from "./controller"; -import { ConsoleHookBody, ConsoleHookQueryString, ConsoleOptions } from "../types"; -import UserServiceAPI from "../../user/api"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; +import { ConsoleHookBody, ConsoleHookQueryString } from "../types"; +import gr from "../../global-resolver"; const hookUrl = "/hook"; -const routes: FastifyPluginCallback<{ - service: ConsoleServiceAPI; - authService: AuthServiceAPI; - userService: UserServiceAPI; - options: ConsoleOptions; -}> = (fastify: FastifyInstance, options, next) => { - const controller = new ConsoleController( - options.service, - options.authService, - options.userService, - options.options, - ); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const controller = new ConsoleController(); const accessControl = async ( request: FastifyRequest<{ Body: ConsoleHookBody; Querystring: ConsoleHookQueryString }>, ) => { - if (options.service.consoleType != "remote") { + if (gr.services.console.consoleType != "remote") { throw fastify.httpErrors.notImplemented("Hook service is only for the remote console"); } if ( (request.body.secret_key || request.query.secret_key) !== - options.service.consoleOptions.hook.token + gr.services.console.consoleOptions.hook.token ) { throw fastify.httpErrors.forbidden("Wrong secret"); } - const publicKey = options.service.consoleOptions.hook.public_key; + const publicKey = gr.services.console.consoleOptions.hook.public_key; if (publicKey) { const input = JSON.stringify({ content: request.body.content, type: request.body.type }); diff --git a/twake/backend/node/src/services/console/web/schemas.ts b/twake/backend/node/src/services/console/web/schemas.ts index 2d5ebc21c5..34db919671 100644 --- a/twake/backend/node/src/services/console/web/schemas.ts +++ b/twake/backend/node/src/services/console/web/schemas.ts @@ -4,7 +4,6 @@ export const consoleHookSchema = { properties: { secret_key: { type: "string" }, }, - required: ["secret_key"], }, body: { type: "object", @@ -12,6 +11,7 @@ export const consoleHookSchema = { type: { type: "string" }, content: { type: "object" }, signature: { type: "string" }, + secret_key: { type: "string" }, }, required: ["type", "content"], }, diff --git a/twake/backend/node/src/services/files/api.ts b/twake/backend/node/src/services/files/api.ts deleted file mode 100644 index 2c95a3a436..0000000000 --- a/twake/backend/node/src/services/files/api.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Readable } from "stream"; -import { Multipart } from "fastify-multipart"; -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; -import { CompanyExecutionContext } from "./web/types"; -import { File } from "./entities/file"; -import { PubsubHandler, PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import { DeleteResult } from "../../core/platform/framework/api/crud-service"; - -export type UploadOptions = { - filename: string; - type: string; - totalSize: number; - totalChunks: number; - chunkNumber: number; - waitForThumbnail: boolean; -}; - -export type DeleteOptions = { - totalChunks?: number; -}; - -export interface FileServiceAPI extends TwakeServiceProvider, Initializable { - pubsub: PubsubServiceAPI; - /** - * Save a file and returns its entity - * - * @param id - * @param file - * @param options - * @param context - */ - save( - id: string, - file: Multipart, - options: UploadOptions, - context: CompanyExecutionContext, - ): Promise; - - /** - * Get a file as readable and metadata information from its ID - * - * @param id - * @param context - */ - download( - id: string, - context: CompanyExecutionContext, - ): Promise<{ file: Readable; name: string; mime: string; size: number }>; - - /** - * Get a thumbnail for download by index - * - * @param id - * @param context - */ - thumbnail( - id: string, - index: string, - context: CompanyExecutionContext, - ): Promise<{ file: Readable; type: string; size: number }>; - - /** - * Get a file entity from its id - * - * @param id - * @param context - */ - get(id: string, context: CompanyExecutionContext): Promise; - - /** - * Delete a file entity from its id - * - * @param id - * @param context - */ - delete(id: string, context: CompanyExecutionContext): Promise>; - - getThumbnailRoute(file: File, index: string): string; - getDownloadRoute(file: File): string; -} - -export interface FilePubsubHandler - extends PubsubHandler { - readonly service: FileServiceAPI; -} diff --git a/twake/backend/node/src/services/files/entities/file.ts b/twake/backend/node/src/services/files/entities/file.ts index 6e486a2cb2..af4541d824 100644 --- a/twake/backend/node/src/services/files/entities/file.ts +++ b/twake/backend/node/src/services/files/entities/file.ts @@ -1,6 +1,6 @@ import { Type } from "class-transformer"; import _ from "lodash"; -import { Entity, Column } from "../../../core/platform/services/database/services/orm/decorators"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; @Entity("files", { primaryKey: [["company_id"], "id"], @@ -86,4 +86,5 @@ export type Thumbnail = { height: number; url: string; + full_url?: string; }; diff --git a/twake/backend/node/src/services/files/index.ts b/twake/backend/node/src/services/files/index.ts index 5638ad3c60..da5bab3d47 100644 --- a/twake/backend/node/src/services/files/index.ts +++ b/twake/backend/node/src/services/files/index.ts @@ -1,37 +1,23 @@ +import { Prefix, TwakeService } from "../../core/platform/framework"; import WebServerAPI from "../../core/platform/services/webserver/provider"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import StorageAPI from "../../core/platform/services/storage/provider"; -import { FileServiceAPI } from "./api"; -import { getService } from "./services/index"; -import web from "./web/index"; +import web from "./web"; @Prefix("/internal/services/files/v1") -@Consumes(["webserver", "database", "storage", "pubsub"]) -export default class FilesService extends TwakeService { +export default class FilesService extends TwakeService { version = "1"; name = "files"; - service: FileServiceAPI; - - api(): FileServiceAPI { - return this.service; - } public async doInit(): Promise { const fastify = this.context.getProvider("webserver").getServer(); - const database = this.context.getProvider("database"); - const storage = this.context.getProvider("storage"); - const pubsub = this.context.getProvider("pubsub"); - - this.service = getService(database, pubsub, storage); - await this.service?.init(this.context); - fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service }); + web(instance, { prefix: this.prefix }); next(); }); - return this; } + + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/files/services/index.ts b/twake/backend/node/src/services/files/services/index.ts index a4e565724c..ffd2e406c7 100644 --- a/twake/backend/node/src/services/files/services/index.ts +++ b/twake/backend/node/src/services/files/services/index.ts @@ -1,60 +1,34 @@ import { randomBytes } from "crypto"; import { Readable } from "stream"; import { Multipart } from "fastify-multipart"; -import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; -import { FileServiceAPI, UploadOptions } from "../api"; -import StorageAPI from "../../../core/platform/services/storage/provider"; +import { UploadOptions } from "../types"; import { File } from "../entities/file"; import Repository from "../../../../src/core/platform/services/database/services/orm/repository/repository"; import { CompanyExecutionContext } from "../web/types"; import { logger } from "../../../core/platform/framework"; -import { - PreviewClearPubsubRequest, - PreviewPubsubRequest, -} from "../../../../src/services/previews/types"; +import { PreviewClearMessageQueueRequest, PreviewMessageQueueRequest } from "../../previews/types"; import { PreviewFinishedProcessor } from "./preview"; import _ from "lodash"; import { getDownloadRoute, getThumbnailRoute } from "../web/routes"; -import { DeleteResult, CrudExeption } from "../../../core/platform/framework/api/crud-service"; - -export function getService( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - storage: StorageAPI, -): FileServiceAPI { - return getServiceInstance(databaseService, pubsub, storage); -} - -function getServiceInstance( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - storage: StorageAPI, -): FileServiceAPI { - return new Service(databaseService, pubsub, storage); -} +import { + CrudException, + DeleteResult, + ExecutionContext, +} from "../../../core/platform/framework/api/crud-service"; +import gr from "../../global-resolver"; -class Service implements FileServiceAPI { +export class FileServiceImpl { version: "1"; repository: Repository; private algorithm = "aes-256-cbc"; private max_preview_file_size = 50000000; - pubsub: PubsubServiceAPI; - - constructor( - readonly database: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - readonly storage: StorageAPI, - ) { - this.pubsub = pubsub; - } async init(): Promise { try { await Promise.all([ - (this.repository = await this.database.getRepository("files", File)), - this.pubsub.processor.addHandler( - new PreviewFinishedProcessor(this, this.pubsub, this.repository), + (this.repository = await gr.database.getRepository("files", File)), + gr.platformServices.messageQueue.processor.addHandler( + new PreviewFinishedProcessor(this, this.repository), ), ]); } catch (err) { @@ -74,10 +48,14 @@ class Service implements FileServiceAPI { let entity: File = null; if (id) { - entity = await this.repository.findOne({ - company_id: context.company.id, - id: id, - }); + entity = await this.repository.findOne( + { + company_id: context.company.id, + id: id, + }, + {}, + context, + ); if (!entity) { throw new Error(`This file ${id} does not exist`); } @@ -97,7 +75,7 @@ class Service implements FileServiceAPI { entity.application_id = applicationId; entity.upload_data = null; - this.repository.save(entity); + this.repository.save(entity, context); } if (file) { @@ -119,7 +97,7 @@ class Service implements FileServiceAPI { size: options.totalSize, chunks: options.totalChunks || 1, }; - this.repository.save(entity); + this.repository.save(entity, context); } } @@ -127,7 +105,7 @@ class Service implements FileServiceAPI { file.file.on("data", function (chunk) { totalUploadedSize += chunk.length; }); - await this.storage.write(getFilePath(entity), file.file, { + await gr.platformServices.storage.write(getFilePath(entity), file.file, { chunkNumber: options.chunkNumber, encryptionAlgo: this.algorithm, encryptionKey: entity.encryption_key, @@ -135,16 +113,16 @@ class Service implements FileServiceAPI { if (entity.upload_data.chunks === 1 && totalUploadedSize) { entity.upload_data.size = totalUploadedSize; - await this.repository.save(entity); + await this.repository.save(entity, context); } //Fixme: detect in multichunk when all chunks are uploaded to trigger this. For now we do only single chunks for preview if (entity.upload_data.chunks === 1 && totalUploadedSize) { /** Send preview generation task */ if (entity.upload_data.size < this.max_preview_file_size) { - const document: PreviewPubsubRequest["document"] = { + const document: PreviewMessageQueueRequest["document"] = { id: JSON.stringify(_.pick(entity, "id", "company_id")), - provider: this.storage.getConnectorType(), + provider: gr.platformServices.storage.getConnectorType(), path: getFilePath(entity), encryption_algo: this.algorithm, @@ -155,7 +133,7 @@ class Service implements FileServiceAPI { mime: entity.metadata.mime, }; const output = { - provider: this.storage.getConnectorType(), + provider: gr.platformServices.storage.getConnectorType(), path: `${getFilePath(entity)}/thumbnails/`, encryption_algo: this.algorithm, encryption_key: entity.encryption_key, @@ -163,19 +141,26 @@ class Service implements FileServiceAPI { }; entity.metadata.thumbnails_status = "waiting"; - await this.repository.save(entity); + await this.repository.save(entity, context); try { - await this.pubsub.publish("services:preview", { - data: { document, output }, - }); + await gr.platformServices.messageQueue.publish( + "services:preview", + { + data: { document, output }, + }, + ); if (options.waitForThumbnail) { - for (let i = 1; i < 10; i++) { - entity = await this.repository.findOne({ - company_id: context.company.id, - id: entity.id, - }); + for (let i = 1; i < 100; i++) { + entity = await this.repository.findOne( + { + company_id: context.company.id, + id: entity.id, + }, + {}, + context, + ); if (entity.metadata.thumbnails_status === "done") { break; } @@ -184,7 +169,7 @@ class Service implements FileServiceAPI { } } catch (err) { entity.metadata.thumbnails_status = "error"; - await this.repository.save(entity); + await this.repository.save(entity, context); logger.warn({ err }, "Previewing - Error while sending "); } @@ -197,16 +182,21 @@ class Service implements FileServiceAPI { return entity; } + async exists(id: string, companyId: string, context?: CompanyExecutionContext): Promise { + const entity = await this.getFile({ id, company_id: companyId }, context); + return !!entity; + } + async download( id: string, context: CompanyExecutionContext, ): Promise<{ file: Readable; name: string; mime: string; size: number }> { - const entity = await this.repository.findOne({ company_id: context.company.id, id: id }); + const entity = await this.get(id, context); if (!entity) { throw "File not found"; } - const readable = await this.storage.read(getFilePath(entity), { + const readable = await gr.platformServices.storage.read(getFilePath(entity), { totalChunks: entity.upload_data.chunks, encryptionAlgo: this.algorithm, encryptionKey: entity.encryption_key, @@ -225,7 +215,7 @@ class Service implements FileServiceAPI { index: string, context: CompanyExecutionContext, ): Promise<{ file: Readable; type: string; size: number }> { - const entity = await this.repository.findOne({ company_id: context.company.id, id: id }); + const entity = await this.get(id, context); if (!entity) { throw "File not found"; @@ -238,7 +228,7 @@ class Service implements FileServiceAPI { const thumbnailPath = `${getFilePath(entity)}/thumbnails/${thumbnail.id}`; - const readable = await this.storage.read(thumbnailPath, { + const readable = await gr.platformServices.storage.read(thumbnailPath, { encryptionAlgo: this.algorithm, encryptionKey: entity.encryption_key, }); @@ -251,7 +241,14 @@ class Service implements FileServiceAPI { } get(id: string, context: CompanyExecutionContext): Promise { - return this.repository.findOne({ id, company_id: context.company.id }); + if (!id || !context.company.id) { + return null; + } + return this.getFile({ id, company_id: context.company.id }, context); + } + + async getFile(pk: Pick, context?: ExecutionContext): Promise { + return this.repository.findOne(pk, {}, context); } getThumbnailRoute(file: File, index: string) { @@ -263,31 +260,34 @@ class Service implements FileServiceAPI { } async delete(id: string, context: CompanyExecutionContext): Promise> { - const fileToDelete = await this.repository.findOne({ id, company_id: context.company.id }); + const fileToDelete = await this.get(id, context); if (!fileToDelete) { - throw new CrudExeption("File not found", 404); + throw new CrudException("File not found", 404); } - await this.repository.remove(fileToDelete); + await this.repository.remove(fileToDelete, context); const path = getFilePath(fileToDelete); - await this.storage.remove(path, { + await gr.platformServices.storage.remove(path, { totalChunks: fileToDelete.upload_data.chunks, }); if (fileToDelete.thumbnails.length > 0) { - await this.pubsub.publish("services:preview:clear", { - data: { - document: { - id: JSON.stringify(_.pick(fileToDelete, "id", "company_id")), - provider: this.storage.getConnectorType(), - path: `${path}/thumbnails/`, - thumbnails_number: fileToDelete.thumbnails.length, + await gr.platformServices.messageQueue.publish( + "services:preview:clear", + { + data: { + document: { + id: JSON.stringify(_.pick(fileToDelete, "id", "company_id")), + provider: gr.platformServices.storage.getConnectorType(), + path: `${path}/thumbnails/`, + thumbnails_number: fileToDelete.thumbnails.length, + }, }, }, - }); + ); } return new DeleteResult("files", fileToDelete, true); diff --git a/twake/backend/node/src/services/files/services/preview.ts b/twake/backend/node/src/services/files/services/preview.ts index 79dac114b4..0c5313a1b4 100644 --- a/twake/backend/node/src/services/files/services/preview.ts +++ b/twake/backend/node/src/services/files/services/preview.ts @@ -1,20 +1,18 @@ -import { FilePubsubHandler, FileServiceAPI } from "../api"; import { logger, TwakeContext } from "../../../core/platform/framework"; -import _ from "lodash"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; -import { PreviewPubsubCallback } from "../../../../src/services/previews/types"; +import { PreviewMessageQueueCallback } from "../../../../src/services/previews/types"; import Repository from "../../../../src/core/platform/services/database/services/orm/repository/repository"; import { File } from "../entities/file"; +import { FileServiceImpl } from "./index"; +import { MessageQueueHandler } from "../../../core/platform/services/message-queue/api"; +import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; /** * Update the file metadata and upload the thumbnails in storage */ -export class PreviewFinishedProcessor implements FilePubsubHandler { - constructor( - readonly service: FileServiceAPI, - private pubsub: PubsubServiceAPI, - private repository: Repository, - ) {} +export class PreviewFinishedProcessor + implements MessageQueueHandler +{ + constructor(readonly service: FileServiceImpl, private repository: Repository) {} async init(context?: TwakeContext): Promise { return this; @@ -31,17 +29,17 @@ export class PreviewFinishedProcessor implements FilePubsubHandler { + async process(message: PreviewMessageQueueCallback, context?: ExecutionContext): Promise { logger.info( - `${this.name} - Updating file metadata with preview generation ${message.thumbnails}`, + `${this.name} - Updating file metadata with preview generation ${message.thumbnails.length}`, ); const pk: { company_id: string; id: string } = JSON.parse(message.document.id); - const entity = await this.repository.findOne(pk); + const entity = await this.repository.findOne(pk, {}, context); if (!entity) { logger.info(`This file ${message.document.id} does not exists anymore.`); @@ -63,7 +61,7 @@ export class PreviewFinishedProcessor implements FilePubsubHandler): PublicFile => { + if ((file as Partial).getPublicObject) file = (file as Partial).getPublicObject(); + return { + ...file, + thumbnails: [ + ...file.thumbnails.map(thumbnail => ({ + ...thumbnail, + full_url: thumbnail.url.match(/https?:\/\//) + ? "/internal/services/files/v1/" + thumbnail.url.replace(/^\//, "") + : thumbnail.url, + })), + ], + } as PublicFile; +}; + +export const fileIsMedia = (file: Partial): boolean => { + return ( + file.metadata?.mime?.startsWith("video/") || + file.metadata?.mime?.startsWith("audio/") || + file.metadata?.mime?.startsWith("image/") + ); +}; diff --git a/twake/backend/node/src/services/files/web/controllers/files.ts b/twake/backend/node/src/services/files/web/controllers/files.ts index c1edde7ad0..35a2024210 100644 --- a/twake/backend/node/src/services/files/web/controllers/files.ts +++ b/twake/backend/node/src/services/files/web/controllers/files.ts @@ -1,13 +1,12 @@ -import { FastifyRequest, FastifyReply } from "fastify"; +import { FastifyReply, FastifyRequest } from "fastify"; import { Multipart } from "fastify-multipart"; import { ResourceDeleteResponse } from "../../../../utils/types"; import { CompanyExecutionContext } from "../types"; -import { FileServiceAPI, UploadOptions } from "../../api"; -import { File, PublicFile } from "../../entities/file"; +import { UploadOptions } from "../../types"; +import { PublicFile } from "../../entities/file"; +import gr from "../../../global-resolver"; export class FileController { - constructor(protected service: FileServiceAPI) {} - async save( request: FastifyRequest<{ Params: { company_id: string; id: string }; @@ -32,7 +31,7 @@ export class FileController { }; const id = request.params.id; - const result = await this.service.save(id, file, options, context); + const result = await gr.services.files.save(id, file, options, context); return { resource: result.getPublicObject(), @@ -45,7 +44,7 @@ export class FileController { ): Promise { const context = getCompanyExecutionContext(request); const params = request.params; - const data = await this.service.download(params.id, context); + const data = await gr.services.files.download(params.id, context); const filename = data.name.replace(/[^a-zA-Z0-9 -_.]/g, ""); response.header("Content-disposition", `attachment; filename="${filename}"`); @@ -61,9 +60,10 @@ export class FileController { const context = getCompanyExecutionContext(request); const params = request.params; try { - const data = await this.service.thumbnail(params.id, params.index, context); + const data = await gr.services.files.thumbnail(params.id, params.index, context); response.header("Content-disposition", "inline"); + response.expires(new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 365)); if (data.size) response.header("Content-Length", data.size); response.type(data.type); response.send(data.file); @@ -79,7 +79,7 @@ export class FileController { ): Promise<{ resource: PublicFile }> { const context = getCompanyExecutionContext(request); const params = request.params; - const resource = await this.service.get(params.id, context); + const resource = await gr.services.files.get(params.id, context); return { resource: resource.getPublicObject() }; } @@ -90,7 +90,7 @@ export class FileController { const params = request.params; const context = getCompanyExecutionContext(request); - const deleteResult = await this.service.delete(params.id, context); + const deleteResult = await gr.services.files.delete(params.id, context); return { status: deleteResult.deleted ? "success" : "error" }; } diff --git a/twake/backend/node/src/services/files/web/index.ts b/twake/backend/node/src/services/files/web/index.ts index 1b91b8b6ee..cc806d3d51 100644 --- a/twake/backend/node/src/services/files/web/index.ts +++ b/twake/backend/node/src/services/files/web/index.ts @@ -1,11 +1,12 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { FileServiceAPI } from "../api"; +import fastifyCaching from "@fastify/caching"; import routes from "./routes"; export default ( fastify: FastifyInstance, - options: FastifyRegisterOptions<{ prefix: string; service: FileServiceAPI }>, + options: FastifyRegisterOptions<{ prefix: string }>, ): void => { fastify.log.debug("Configuring /internal/services/files/v1 routes"); + fastify.register(fastifyCaching, { expiresIn: 31536000, privacy: fastifyCaching.privacy.PUBLIC }); fastify.register(routes, options); }; diff --git a/twake/backend/node/src/services/files/web/routes.ts b/twake/backend/node/src/services/files/web/routes.ts index abcfc47b48..a9e0442899 100644 --- a/twake/backend/node/src/services/files/web/routes.ts +++ b/twake/backend/node/src/services/files/web/routes.ts @@ -1,16 +1,11 @@ import { FastifyInstance, FastifyPluginCallback } from "fastify"; -import { FileServiceAPI } from "../api"; -import { FileController } from "./controllers/files"; +import { FileController } from "./controllers"; import { File } from "../entities/file"; const filesUrl = "/companies/:company_id/files"; -const routes: FastifyPluginCallback<{ service: FileServiceAPI }> = ( - fastify: FastifyInstance, - options, - next, -) => { - const fileController = new FileController(options.service); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const fileController = new FileController(); fastify.route({ method: "POST", @@ -60,7 +55,7 @@ export const getDownloadRoute = (file: File) => { }; export const getThumbnailRoute = (file: File, index: string) => { - return filesUrl.replace(":company_id", file.company_id) + `/${file.id}/thumbnails/${index}`; + return `/internal/services/files/v1/companies/${file.company_id}/files/${file.id}/thumbnails/${index}`; }; export default routes; diff --git a/twake/backend/node/src/services/files/web/schemas.ts b/twake/backend/node/src/services/files/web/schemas.ts index 52e7cc4776..c664135c43 100644 --- a/twake/backend/node/src/services/files/web/schemas.ts +++ b/twake/backend/node/src/services/files/web/schemas.ts @@ -1,3 +1,5 @@ +import { userObjectSchema } from "../../user/web/schemas"; + export const filesSchema = { type: "object", properties: { diff --git a/twake/backend/node/src/services/general/api.ts b/twake/backend/node/src/services/general/api.ts index 77c81e646e..00fc56fc99 100644 --- a/twake/backend/node/src/services/general/api.ts +++ b/twake/backend/node/src/services/general/api.ts @@ -1,3 +1,3 @@ -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; +import { Initializable, TwakeServiceProvider } from "../../core/platform/framework/api"; export interface GeneralServiceAPI extends TwakeServiceProvider, Initializable {} diff --git a/twake/backend/node/src/services/general/index.ts b/twake/backend/node/src/services/general/index.ts index af16b65bfc..a1e5a617da 100644 --- a/twake/backend/node/src/services/general/index.ts +++ b/twake/backend/node/src/services/general/index.ts @@ -1,5 +1,5 @@ import WebServerAPI from "../../core/platform/services/webserver/provider"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; +import { Consumes, Prefix, TwakeService } from "../../core/platform/framework"; import { GeneralServiceAPI } from "./api"; import web from "./web/index"; import { ServerConfiguration } from "./types"; diff --git a/twake/backend/node/src/services/general/languages.ts b/twake/backend/node/src/services/general/languages.ts index 77f0fe59ac..491aa8036b 100644 --- a/twake/backend/node/src/services/general/languages.ts +++ b/twake/backend/node/src/services/general/languages.ts @@ -1,4 +1,4 @@ -import { Languages, ServerConfiguration } from "./types"; +import { Languages } from "./types"; export const languages: Languages = { default: "en", diff --git a/twake/backend/node/src/services/general/types.ts b/twake/backend/node/src/services/general/types.ts index 0390912e8d..67e9686502 100644 --- a/twake/backend/node/src/services/general/types.ts +++ b/twake/backend/node/src/services/general/types.ts @@ -15,6 +15,12 @@ export type ServerConfiguration = { configuration: { help_url: string | null; pricing_plan_url: string | null; + app_download_url: string | null; + mobile: { + mobile_redirect: string; + mobile_appstore: string; + mobile_googleplay: string; + }; accounts: { type: "console" | "internal"; console: null | { diff --git a/twake/backend/node/src/services/general/web/index.ts b/twake/backend/node/src/services/general/web/index.ts index a4ae6a74b2..a78077fdae 100644 --- a/twake/backend/node/src/services/general/web/index.ts +++ b/twake/backend/node/src/services/general/web/index.ts @@ -1,5 +1,4 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { GeneralServiceAPI } from "../api"; import { ServerConfiguration } from "../types"; import routes from "./routes"; diff --git a/twake/backend/node/src/services/general/web/routes.ts b/twake/backend/node/src/services/general/web/routes.ts index a9b866dfc2..76fbd45b26 100644 --- a/twake/backend/node/src/services/general/web/routes.ts +++ b/twake/backend/node/src/services/general/web/routes.ts @@ -18,7 +18,13 @@ const routes: FastifyPluginCallback<{ configuration: ServerConfiguration["config status: "ready", version: version, configuration: { - ..._.pick(options.configuration, "help_url", "pricing_plan_url"), + ..._.pick( + options.configuration, + "help_url", + "pricing_plan_url", + "mobile", + "app_download_url", + ), accounts: { type: accounts.type, console: _.pick( diff --git a/twake/backend/node/src/services/global-resolver.ts b/twake/backend/node/src/services/global-resolver.ts new file mode 100644 index 0000000000..d8ae90e959 --- /dev/null +++ b/twake/backend/node/src/services/global-resolver.ts @@ -0,0 +1,216 @@ +import { FastifyInstance } from "fastify"; +import { IncomingMessage, Server, ServerResponse } from "http"; + +import { TwakePlatform } from "../core/platform/platform"; +import { RealtimeServiceAPI } from "../core/platform/services/realtime/api"; +import WebServerAPI from "../core/platform/services/webserver/provider"; +import { SearchServiceAPI } from "../core/platform/services/search/api"; +import StorageAPI from "../core/platform/services/storage/provider"; +import { MessageQueueServiceAPI } from "../core/platform/services/message-queue/api"; +import { CounterAPI } from "../core/platform/services/counter/types"; +import { DatabaseServiceAPI } from "../core/platform/services/database/api"; +import AuthServiceAPI from "../core/platform/services/auth/provider"; +import { PushServiceAPI } from "../core/platform/services/push/api"; +import { CronAPI } from "../core/platform/services/cron/api"; +import WebSocketAPI from "../core/platform/services/websocket/provider"; +import TrackerAPI from "../core/platform/services/tracker/provider"; +import KnowledgeGraphService from "../core/platform/services/knowledge-graph"; +import EmailPusherAPI from "../core/platform/services/email-pusher/provider"; + +import { logger } from "../core/platform/framework"; +import assert from "assert"; +import { CompanyServiceImpl } from "./user/services/companies"; +import { WorkspaceServiceImpl } from "./workspaces/services/workspace"; +import { UserExternalLinksServiceImpl } from "./user/services/external_links"; +import { UserNotificationBadgeService } from "./notifications/services/bages"; +import { NotificationPreferencesService } from "./notifications/services/preferences"; +import { ThreadMessagesService } from "./messages/services/messages"; +import { MessagesFilesService } from "./messages/services/messages-files"; +import { ThreadsService } from "./messages/services/threads"; +import { UserBookmarksService } from "./messages/services/user-bookmarks"; +import { UserServiceImpl } from "./user/services/users/service"; +import { CompanyApplicationServiceImpl } from "./applications/services/company-applications"; +import { ApplicationServiceImpl } from "./applications/services/applications"; +import { ViewsServiceImpl } from "./messages/services/views"; +import { MessagesEngine } from "./messages/services/engine"; +import { FileServiceImpl } from "./files/services"; +import { ChannelServiceImpl } from "./channels/services/channel/service"; +import { MemberServiceImpl } from "./channels/services/member/service"; +import ChannelPendingEmailServiceImpl from "./channels/services/channel/pending-emails/service"; +import { TabServiceImpl } from "./channels/services/tab"; +import { ConsoleServiceImpl } from "./console/service"; +import { StatisticsServiceImpl } from "./statistics/service"; +import { NotificationEngine } from "./notifications/services/engine"; +import { MobilePushService } from "./notifications/services/mobile-push"; +import { ChannelMemberPreferencesServiceImpl } from "./notifications/services/channel-preferences"; +import { ChannelThreadUsersServiceImpl } from "./notifications/services/channel-thread-users"; +import { PreviewProcessService } from "./previews/services/files/processing/service"; +import { ApplicationHooksService } from "./applications/services/hooks"; +import OnlineServiceImpl from "./online/service"; +import { PreviewEngine } from "./previews/services/files/engine"; +import { ChannelsMessageQueueListener } from "./channels/services/pubsub"; +import { LinkPreviewProcessService } from "./previews/services/links/processing/service"; +import { LinkPreviewEngine } from "./previews/services/links/engine"; +import { UserNotificationDigestService } from "./notifications/services/digest"; + +type PlatformServices = { + auth: AuthServiceAPI; + counter: CounterAPI; + cron: CronAPI; + messageQueue: MessageQueueServiceAPI; + push: PushServiceAPI; + realtime: RealtimeServiceAPI; + search: SearchServiceAPI; + storage: StorageAPI; + tracker: TrackerAPI; + webserver: WebServerAPI; + websocket: WebSocketAPI; + knowledgeGraph: KnowledgeGraphService; + emailPusher: EmailPusherAPI; +}; + +type TwakeServices = { + workspaces: WorkspaceServiceImpl; + companies: CompanyServiceImpl; + users: UserServiceImpl; + console: ConsoleServiceImpl; + statistics: StatisticsServiceImpl; + externalUser: UserExternalLinksServiceImpl; + notifications: { + badges: UserNotificationBadgeService; + channelPreferences: ChannelMemberPreferencesServiceImpl; + channelThreads: ChannelThreadUsersServiceImpl; + engine: NotificationEngine; + preferences: NotificationPreferencesService; + mobilePush: MobilePushService; + digest: UserNotificationDigestService; + }; + preview: { + files: PreviewProcessService; + links: LinkPreviewProcessService; + }; + messages: { + messages: ThreadMessagesService; + messagesFiles: MessagesFilesService; + threads: ThreadsService; + userBookmarks: UserBookmarksService; + views: ViewsServiceImpl; + engine: MessagesEngine; + }; + applications: { + marketplaceApps: ApplicationServiceImpl; + companyApps: CompanyApplicationServiceImpl; + hooks: ApplicationHooksService; + }; + files: FileServiceImpl; + channels: { + channels: ChannelServiceImpl; + members: MemberServiceImpl; + pubsub: ChannelsMessageQueueListener; + }; + channelPendingEmail: ChannelPendingEmailServiceImpl; + tab: TabServiceImpl; + online: OnlineServiceImpl; +}; + +class GlobalResolver { + public services: TwakeServices; + public platformServices: PlatformServices; + public database: DatabaseServiceAPI; + + public fastify: FastifyInstance; + + private alreadyInitialized = false; + + async doInit(platform: TwakePlatform) { + if (this.alreadyInitialized) { + return; + } + this.database = platform.getProvider("database"); + + this.platformServices = { + auth: platform.getProvider("auth"), + counter: platform.getProvider("counter"), + cron: platform.getProvider("cron"), + messageQueue: platform.getProvider("message-queue"), + push: platform.getProvider("push"), + realtime: platform.getProvider("realtime"), + search: platform.getProvider("search"), + storage: platform.getProvider("storage"), + tracker: platform.getProvider("tracker"), + webserver: platform.getProvider("webserver"), + websocket: platform.getProvider("websocket"), + knowledgeGraph: await new KnowledgeGraphService().init(), + emailPusher: platform.getProvider("email-pusher"), + }; + + this.fastify = this.platformServices.webserver.getServer(); + + Object.keys(this.platformServices).forEach((key: keyof PlatformServices) => { + const service = this.platformServices[key]; + assert(service, `Platform service ${key} was not initialized`); + }); + + await new PreviewEngine().init(); + await new LinkPreviewEngine().init(); + + this.services = { + workspaces: await new WorkspaceServiceImpl().init(), + companies: await new CompanyServiceImpl().init(), + users: await new UserServiceImpl().init(), + console: await new ConsoleServiceImpl().init(), + statistics: await new StatisticsServiceImpl().init(), + externalUser: await new UserExternalLinksServiceImpl().init(), + notifications: { + badges: await new UserNotificationBadgeService().init(platform), + channelPreferences: await new ChannelMemberPreferencesServiceImpl().init(), + channelThreads: await new ChannelThreadUsersServiceImpl().init(), + engine: await new NotificationEngine().init(), + preferences: await new NotificationPreferencesService().init(), + mobilePush: await new MobilePushService().init(), + digest: await new UserNotificationDigestService().init(), + }, + preview: { + files: await new PreviewProcessService().init(), + links: await new LinkPreviewProcessService().init(), + }, + messages: { + messages: await new ThreadMessagesService().init(platform), + messagesFiles: await new MessagesFilesService().init(), + threads: await new ThreadsService().init(platform), + userBookmarks: await new UserBookmarksService().init(platform), + views: await new ViewsServiceImpl().init(platform), + engine: await new MessagesEngine().init(), + }, + applications: { + marketplaceApps: await new ApplicationServiceImpl().init(), + companyApps: await new CompanyApplicationServiceImpl().init(), + hooks: await new ApplicationHooksService().init(), + }, + files: await new FileServiceImpl().init(), + channels: { + channels: await new ChannelServiceImpl().init(), + members: await new MemberServiceImpl().init(), + pubsub: await new ChannelsMessageQueueListener().init(), + }, + channelPendingEmail: await new ChannelPendingEmailServiceImpl().init(), + tab: await new TabServiceImpl().init(), + online: await new OnlineServiceImpl().init(), + }; + + Object.keys(this.services).forEach((key: keyof TwakeServices) => { + assert(this.services[key], `Service ${key} was not initialized`); + if (this.services[key].constructor.name == "Object") { + const subs = this.services[key] as any; + Object.keys(subs).forEach(sk => { + assert(subs[sk], `Service ${key}.${sk} was not initialized`); + }); + } + }); + + logger.info("Global resolver finished initializing services"); + this.alreadyInitialized = true; + } +} + +export default new GlobalResolver(); diff --git a/twake/backend/node/src/services/messages/api.ts b/twake/backend/node/src/services/messages/api.ts deleted file mode 100644 index 1355725669..0000000000 --- a/twake/backend/node/src/services/messages/api.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { - CRUDService, - DeleteResult, - ExecutionContext, - ListResult, - Paginable, - Pagination, - SaveResult, -} from "../../core/platform/framework/api/crud-service"; -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; -import { - UserMessageBookmark, - UserMessageBookmarkPrimaryKey, -} from "./entities/user-message-bookmarks"; -import { MessagesEngine } from "./services/engine"; - -import { - ChannelViewExecutionContext, - CompanyExecutionContext, - MessageViewListOptions, - ThreadExecutionContext, - MessageWithReplies, - MessagesGetThreadOptions, - MessageWithRepliesWithUsers, -} from "./types"; - -import { ParticipantObject, Thread, ThreadPrimaryKey } from "./entities/threads"; -import { Message, MessagePrimaryKey, MessageWithUsers } from "./entities/messages"; -import { StatisticsAPI } from "../statistics/types"; -import { SearchUserOptions } from "../user/services/users/types"; -import { uuid } from "../../utils/types"; - -export interface MessageServiceAPI extends TwakeServiceProvider, Initializable { - userBookmarks: MessageUserBookmarksServiceAPI; - threads: MessageThreadsServiceAPI; - messages: MessageThreadMessagesServiceAPI; - views: MessageViewsServiceAPI; - engine: MessagesEngine; - statistics: StatisticsAPI; -} - -export interface MessageUserBookmarksServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - list( - pagination: Paginable, - options?: ListOptions, - context?: CompanyExecutionContext, - ): Promise>; -} - -export interface MessageThreadsServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - addReply(thread_id: string, increment?: number): Promise; - setReplyCount(thread_id: string, count: number): Promise; - save( - item: Pick & { - participants: Pick[]; - }, - options?: { participants?: any; message?: Message }, - context?: CompanyExecutionContext, - ): Promise>; - - checkAccessToThread(context: ThreadExecutionContext): Promise; -} - -export interface MessageThreadMessagesServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - pin( - item: { id: string; pin: boolean }, - options: Record, - context: ThreadExecutionContext, - ): Promise>; - - reaction( - item: { id: string; reactions: string[] }, - options: Record, - context: ThreadExecutionContext, - ): Promise>; - - save( - item: Message, - options?: SaveOptions, - context?: ThreadExecutionContext, - ): Promise>; - - bookmark( - item: { id: string; bookmark_id: string; active: boolean }, - options: Record, - context: ThreadExecutionContext, - ): Promise>; - - forceDelete( - pk: Pick, - context?: ThreadExecutionContext, - ): Promise>; - - getThread(thread: Thread, options: MessagesGetThreadOptions): Promise; - - move( - item: Pick, - options: { previous_thread: string }, - context: ThreadExecutionContext, - ): Promise; - - includeUsersInMessage(message: Message): Promise; - includeUsersInMessageWithReplies( - message: MessageWithReplies, - ): Promise; -} - -export interface MessageViewsServiceAPI extends TwakeServiceProvider, Initializable { - listChannel( - pagination: Paginable, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise>; - - listChannelFiles( - pagination: Paginable, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise>; - - listChannelThreads( - pagination: Paginable, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise>; - - listChannelPinned( - pagination: Paginable, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise>; - - search( - pagination: Pagination, - options?: SearchUserOptions, - context?: ExecutionContext, - ): Promise>; - - getThreadsFirstMessages(threadsIds: uuid[]): Promise; -} diff --git a/twake/backend/node/src/services/messages/blocks-types.ts b/twake/backend/node/src/services/messages/blocks-types.ts index 0e37a19b64..3dfcdffe65 100644 --- a/twake/backend/node/src/services/messages/blocks-types.ts +++ b/twake/backend/node/src/services/messages/blocks-types.ts @@ -15,42 +15,42 @@ export type Block = { block_id?: string } & ( | BlockTwacode ); -type BlockTwacode = { +export type BlockTwacode = { type: "twacode"; elements: any; }; -type BlockActions = { +export type BlockActions = { type: "actions"; elements: BlockElement[]; }; -type BlockContext = { +export type BlockContext = { type: "context"; - elements: (BlockElementImage | CompositionTextObject)[]; + elements: (BlockElementImage | CompositionTextObject | BlockElementProgressBar)[]; }; -type BlockHeader = { +export type BlockHeader = { type: "header"; text: CompositionPlainTextObject; }; -type BlockDivider = { +export type BlockDivider = { type: "divider"; }; -type BlockFile = { +export type BlockFile = { type: "file"; external_id: string; source: string; metadata?: MessageFileMetadata; }; -type BlockImage = BlockElementImage & { +export type BlockImage = BlockElementImage & { title?: CompositionPlainTextObject; }; -type BlockInput = { +export type BlockInput = { type: "input"; label: string; element: BlockElement; @@ -59,14 +59,14 @@ type BlockInput = { optional?: boolean; }; -type BlockSection = { +export type BlockSection = { type: "section"; text?: CompositionTextObject; fields?: CompositionTextObject[]; accessory?: BlockElement; }; -type BlockIframe = { +export type BlockIframe = { type: "iframe"; iframe_url: string; width: number; @@ -77,6 +77,7 @@ type BlockIframe = { export type BlockElement = | BlockElementImage + | BlockElementProgressBar | BlockElementButton | BlockElementCheckboxes | BlockElementDatePicker @@ -87,14 +88,21 @@ export type BlockElement = | BlockElementOverflowMenus | BlockElementTimePicker; -type BlockElementImage = { +export type BlockElementImage = { type: "image"; image_url: string; alt_text: string; + title?: any; metadata?: MessageFileMetadata; }; -type BlockElementButton = { +export type BlockElementProgressBar = { + type: "progress_bar"; + value: number; //Between 0 and 100 + title: string; +}; + +export type BlockElementButton = { type: "button"; text: CompositionPlainTextObject; action_id: string; @@ -104,7 +112,7 @@ type BlockElementButton = { confirm?: CompositionConfirmationDialog; }; -type BlockElementCheckboxes = { +export type BlockElementCheckboxes = { type: "checkboxes"; action_id: string; options: CompositionOption[]; @@ -121,9 +129,11 @@ type BlockElementPlaintextInput = { min_length?: number; max_length?: number; dispatch_action_config?: DispatchActionConfiguration; + readonly?: boolean; + copiable?: boolean; }; -type BlockElementRadioButtonInput = { +export type BlockElementRadioButtonInput = { type: "radio_buttons"; action_id: string; options: CompositionOption[]; @@ -131,7 +141,7 @@ type BlockElementRadioButtonInput = { confirm?: CompositionConfirmationDialog; }; -type BlockElementDatePicker = { +export type BlockElementDatePicker = { type: "datepicker"; action_id: string; placeholder?: CompositionPlainTextObject; @@ -139,7 +149,7 @@ type BlockElementDatePicker = { confirm?: CompositionConfirmationDialog; }; -type BlockElementTimePicker = { +export type BlockElementTimePicker = { type: "timepicker"; action_id: string; placeholder?: CompositionPlainTextObject; @@ -147,19 +157,19 @@ type BlockElementTimePicker = { confirm?: CompositionConfirmationDialog; }; -type BlockElementOverflowMenus = { +export type BlockElementOverflowMenus = { type: "overflow"; action_id: string; options: CompositionOption[]; confirm?: CompositionConfirmationDialog; }; -type BlockElementSelectMenus = { +export type BlockElementSelectMenus = { type: ""; }; //TODO -type BlockElementMultiselectMenu = { - type: ""; +export type BlockElementMultiselectMenu = { + type: any; }; //TODO /* Composition objects */ @@ -169,6 +179,8 @@ type CompositionTextObject = CompositionPlainTextObject | CompositionMarkdownTex type CompositionPlainTextObject = { type: "plain_text"; text: string; + emoji?: boolean; + verbatim?: boolean; }; type CompositionMarkdownTextObject = { diff --git a/twake/backend/node/src/services/messages/entities/message-file-refs.ts b/twake/backend/node/src/services/messages/entities/message-file-refs.ts index 836ba98a84..07bed53795 100644 --- a/twake/backend/node/src/services/messages/entities/message-file-refs.ts +++ b/twake/backend/node/src/services/messages/entities/message-file-refs.ts @@ -4,13 +4,13 @@ import { Column, Entity } from "../../../core/platform/services/database/service export const TYPE = "message_file_refs"; @Entity(TYPE, { - primaryKey: [["target_type", "target_id"], "id"], + primaryKey: [["target_type", "company_id", "target_id"], "id"], type: TYPE, }) export class MessageFileRef { @Type(() => String) @Column("target_type", "string") - target_type: "channel" | "user_upload" | "user_download"; + target_type: "channel" | "channel_media" | "channel_file" | "user_upload" | "user_download"; @Type(() => String) @Column("target_id", "string") @@ -41,8 +41,15 @@ export class MessageFileRef { message_id: string; @Type(() => String) - @Column("file_id", "string") + @Column("message_file_id", "string") + message_file_id: string; + + @Type(() => String) + @Column("file_id", "json") file_id: string; + + @Column("company_id", "timeuuid") + company_id: string; } export type MessageFileRefPrimaryKey = Pick; diff --git a/twake/backend/node/src/services/messages/entities/message-files.search.ts b/twake/backend/node/src/services/messages/entities/message-files.search.ts new file mode 100644 index 0000000000..16c9a4fcf9 --- /dev/null +++ b/twake/backend/node/src/services/messages/entities/message-files.search.ts @@ -0,0 +1,54 @@ +import _ from "lodash"; +import { fileIsMedia } from "../../../services/files/utils"; +import { MessageFile } from "./message-files"; + +export const expandFileNameForSearch = (name: string) => { + return name + " " + _.snakeCase(name).replace(/[^a-zA-Z0-9]/gm, " "); +}; + +export default { + index: "message_files", + source: (entity: MessageFile) => { + const isMedia = fileIsMedia(entity); + + const source = { + name: expandFileNameForSearch(entity.metadata?.name || ""), + size: entity.metadata?.size || "", + source: entity.metadata?.source || "", + extension: (entity.metadata?.name || "").split(".").pop() || "", + is_media: isMedia, + is_file: !isMedia, + created_at: entity.created_at, + + cache_company_id: entity.cache?.company_id, + cache_workspace_id: entity.cache?.workspace_id, + cache_channel_id: entity.cache?.channel_id, + cache_user_id: entity.cache?.user_id, + }; + return source; + }, + mongoMapping: { + text: { + name: "text", + }, + prefix: { + name: "prefix", + }, + }, + esMapping: { + properties: { + name: { type: "text", index_prefixes: { min_chars: 1, max_chars: 20 } }, + size: { type: "number" }, + source: { type: "keyword" }, + extension: { type: "keyword" }, + is_media: { type: "boolean" }, + is_file: { type: "boolean" }, + created_at: { type: "number" }, + + cache_company_id: { type: "keyword" }, + cache_workspace_id: { type: "keyword" }, + cache_channel_id: { type: "keyword" }, + cache_user_id: { type: "keyword" }, + }, + }, +}; diff --git a/twake/backend/node/src/services/messages/entities/message-files.ts b/twake/backend/node/src/services/messages/entities/message-files.ts index b479787f16..35524e1ba1 100644 --- a/twake/backend/node/src/services/messages/entities/message-files.ts +++ b/twake/backend/node/src/services/messages/entities/message-files.ts @@ -2,26 +2,44 @@ import { Type } from "class-transformer"; import { merge } from "lodash"; import { Thumbnail } from "../../files/entities/file"; import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; +import search from "./message-files.search"; export const TYPE = "message_files"; @Entity(TYPE, { primaryKey: [["message_id"], "id"], type: TYPE, + search, }) export class MessageFile { @Type(() => String) @Column("message_id", "timeuuid", { order: "DESC" }) message_id?: string; + //Timeuuid is used please do not change to uuid @Type(() => String) @Column("id", "timeuuid", { order: "DESC" }) - id?: string; + id: string; + + @Type(() => String) + @Column("thread_id", "string") + thread_id?: string; @Column("company_id", "timeuuid") - company_id?: string; + company_id: string; + + @Column("created_at", "number") + created_at: number; @Column("metadata", "encoded_json") metadata: MessageFileMetadata; + + @Column("cache", "encoded_json") + cache: null | { + company_id: string; + workspace_id: string; + channel_id: string; + user_id: string; + }; } export type MessageFileMetadata = { @@ -35,7 +53,3 @@ export type MessageFileMetadata = { }; export type MessageFilePrimaryKey = Pick; - -export function getInstance(file: MessageFile): MessageFile { - return merge(new MessageFile(), file); -} diff --git a/twake/backend/node/src/services/messages/entities/messages.search.ts b/twake/backend/node/src/services/messages/entities/messages.search.ts index c8ce657413..9b85f2e17a 100644 --- a/twake/backend/node/src/services/messages/entities/messages.search.ts +++ b/twake/backend/node/src/services/messages/entities/messages.search.ts @@ -1,17 +1,37 @@ -import { expandStringForPrefix } from "../../../core/platform/services/search/adapters/utils"; +import { fileIsMedia } from "../../../services/files/utils"; +import { expandFileNameForSearch } from "./message-files.search"; import { Message } from "./messages"; export default { index: "messages", source: (entity: Message) => { + const links = ( + (entity.text || "").match( + /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/gi, + ) || [] + ).join(" "); const source: any = { - text: entity.text, + created_at: entity.created_at, + text: entity.text || "", + has_files: (entity.files || []).length > 0, + has_medias: (entity.files || []).filter(f => fileIsMedia(f)).length > 0, + attachments_names: (entity.files || []) + .map(file => expandFileNameForSearch(file.metadata.name)) + .join(" "), + links: + links + + " " + + links.replace(/https?:\/\//gm, "") + + " " + + links.replace(/[^A-Z-a-z0-9]/gm, " "), }; if (entity.cache) { return { company_id: entity.cache?.company_id, workspace_id: entity.cache?.workspace_id, channel_id: entity.cache?.channel_id, + user_id: entity.user_id, + ...source, }; } @@ -25,9 +45,15 @@ export default { esMapping: { properties: { text: { type: "text" }, + attachments_names: { type: "text", index_prefixes: { min_chars: 1 } }, + links: { type: "text", index_prefixes: { min_chars: 1 } }, + user_id: { type: "keyword" }, company_id: { type: "keyword" }, workspace_id: { type: "keyword" }, channel_id: { type: "keyword" }, + has_files: { type: "boolean" }, + has_medias: { type: "boolean" }, + created_at: { type: "number" }, }, }, }; diff --git a/twake/backend/node/src/services/messages/entities/messages.ts b/twake/backend/node/src/services/messages/entities/messages.ts index 694b983fd5..0313f73806 100644 --- a/twake/backend/node/src/services/messages/entities/messages.ts +++ b/twake/backend/node/src/services/messages/entities/messages.ts @@ -60,7 +60,7 @@ export class Message { blocks: Block[]; @Column("files", "encoded_json") - files: null | MessageFile[]; + files: null | Partial[]; @Column("context", "encoded_json") context: any; @@ -71,6 +71,9 @@ export class Message { @Column("pinned_info", "encoded_json") pinned_info: null | MessagePinnedInfo; + @Column("quote_message", "encoded_json") + quote_message: null | Partial; + @Column("reactions", "encoded_json") reactions: null | MessageReaction[]; @@ -86,6 +89,12 @@ export class Message { workspace_id: string; channel_id: string; }; + + @Column("links", "encoded_json") + links: null | MessageLinks[]; + + @Column("status", "encoded_json") + status: null | MessageDeliveryStatus; } export type MessageReaction = { count: number; name: string; users: string[] }; @@ -125,7 +134,20 @@ export function getInstance(message: Partial): Message { }); } -export class MessageWithUsers extends Message { - users: UserObject[]; +export type MessageWithUsers = Message & { + users?: UserObject[]; application?: Partial; -} +}; + +export type MessageLinks = { + title: string; + description: string | null; + domain: string; + img: string | null; + favicon: string | null; + img_width: number | null; + img_height: number | null; + url: string; +}; + +export type MessageDeliveryStatus = "sent" | "delivered" | "read"; diff --git a/twake/backend/node/src/services/messages/entities/user-message-bookmarks.ts b/twake/backend/node/src/services/messages/entities/user-message-bookmarks.ts index e82beb4695..a3a0117ce5 100644 --- a/twake/backend/node/src/services/messages/entities/user-message-bookmarks.ts +++ b/twake/backend/node/src/services/messages/entities/user-message-bookmarks.ts @@ -22,7 +22,7 @@ export class UserMessageBookmark { @Type(() => String) @Column("name", "encoded_string") - name: string = ""; + name = ""; } export type UserMessageBookmarkPrimaryKey = Pick< diff --git a/twake/backend/node/src/services/messages/index.ts b/twake/backend/node/src/services/messages/index.ts index c802901c3a..1e0ea84c91 100644 --- a/twake/backend/node/src/services/messages/index.ts +++ b/twake/backend/node/src/services/messages/index.ts @@ -1,57 +1,23 @@ +import { Prefix, TwakeService } from "../../core/platform/framework"; import WebServerAPI from "../../core/platform/services/webserver/provider"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { MessageServiceAPI } from "./api"; -import { getService } from "./services/index"; -import web from "./web/index"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import UserServiceAPI from "../user/api"; -import ChannelServiceAPI from "../channels/provider"; -import { FileServiceAPI } from "../files/api"; -import { ApplicationServiceAPI } from "../applications/api"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import { StatisticsAPI } from "../statistics/types"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; +import web from "./web"; @Prefix("/internal/services/messages/v1") -@Consumes([ - "webserver", - "database", - "pubsub", - "channels", - "user", - "files", - "applications", - "platform-services", - "statistics", -]) -export default class MessageService extends TwakeService { +export default class MessageService extends TwakeService { version = "1"; name = "messages"; - service: MessageServiceAPI; - - api(): MessageServiceAPI { - return this.service; - } public async doInit(): Promise { const fastify = this.context.getProvider("webserver").getServer(); - const user = this.context.getProvider("user"); - const channels = this.context.getProvider("channels"); - const files = this.context.getProvider("files"); - const applications = this.context.getProvider("applications"); - const platformServices = this.context.getProvider("platform-services"); - const statistics = this.context.getProvider("statistics"); - const realtime = this.context.getProvider("realtime"); - - this.service = getService(platformServices, user, channels, files, applications, statistics); - await this.service?.init(this.context); - fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + web(instance, { prefix: this.prefix }); next(); }); - return this; } + + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/messages/services/engine/index.ts b/twake/backend/node/src/services/messages/services/engine/index.ts index 51b3eec945..783ead1748 100644 --- a/twake/backend/node/src/services/messages/services/engine/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/index.ts @@ -1,9 +1,7 @@ -import { localEventBus } from "../../../../core/platform/framework/pubsub"; -import { Initializable, logger } from "../../../../core/platform/framework"; -import { MessageServiceAPI } from "../../api"; -import { MessageLocalEvent } from "../../types"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; +import { Initializable } from "../../../../core/platform/framework"; +import { MessageFileDownloadEvent, MessageLocalEvent } from "../../types"; import { ChannelViewProcessor } from "./processors/channel-view"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; import { ChannelMarkedViewProcessor } from "./processors/channel-marked"; import { UserMarkedViewProcessor } from "./processors/user-marked"; import { UserInboxViewProcessor } from "./processors/user-inbox"; @@ -11,14 +9,15 @@ import { FilesViewProcessor } from "./processors/files"; import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; import { Thread } from "../../entities/threads"; import { ChannelSystemActivityMessageProcessor } from "./processors/system-activity-message"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; import { MessageToNotificationsProcessor } from "./processors/message-to-notifications"; import { ResourceEventsPayload } from "../../../../utils/types"; -import UserServiceAPI from "../../../user/api"; -import ChannelServiceAPI from "../../../channels/provider"; import _ from "lodash"; import { StatisticsMessageProcessor } from "../../../statistics/pubsub/messages"; -import { StatisticsAPI } from "../../../statistics/types"; +import { MessageToHooksProcessor } from "./processors/message-to-hooks"; +import gr from "../../../global-resolver"; +import { MessageLinksPreviewFinishedProcessor } from "./processors/links"; +import { Message } from "../../entities/messages"; +import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; export class MessagesEngine implements Initializable { private channelViewProcessor: ChannelViewProcessor; @@ -27,35 +26,34 @@ export class MessagesEngine implements Initializable { private userInboxViewProcessor: UserInboxViewProcessor; private filesViewProcessor: FilesViewProcessor; private messageToNotifications: MessageToNotificationsProcessor; + private messageToHooks: MessageToHooksProcessor; private threadRepository: Repository; + private messageRepository: Repository; - constructor( - private database: DatabaseServiceAPI, - private pubsub: PubsubServiceAPI, - private user: UserServiceAPI, - private channel: ChannelServiceAPI, - private service: MessageServiceAPI, - private statistics: StatisticsAPI, - ) { - this.channelViewProcessor = new ChannelViewProcessor(this.database, this.service); - this.channelMarkedViewProcessor = new ChannelMarkedViewProcessor(this.database, this.service); - this.userMarkedViewProcessor = new UserMarkedViewProcessor(this.database, this.service); - this.userInboxViewProcessor = new UserInboxViewProcessor(this.database, this.service); - this.filesViewProcessor = new FilesViewProcessor(this.database, this.service); - this.messageToNotifications = new MessageToNotificationsProcessor( - this.database, - this.pubsub, - this.user, - this.channel, - this.service, - ); + constructor() { + this.channelViewProcessor = new ChannelViewProcessor(); + this.channelMarkedViewProcessor = new ChannelMarkedViewProcessor(); + this.userMarkedViewProcessor = new UserMarkedViewProcessor(); + this.userInboxViewProcessor = new UserInboxViewProcessor(); + this.filesViewProcessor = new FilesViewProcessor(); + this.messageToNotifications = new MessageToNotificationsProcessor(); + this.messageToHooks = new MessageToHooksProcessor(); } - async dispatchMessage(e: MessageLocalEvent) { - const thread = await this.threadRepository.findOne({ - id: e.resource.thread_id, - }); + async dispatchMessage(e: MessageLocalEvent, context?: ExecutionContext) { + const thread = await this.threadRepository.findOne( + { + id: e.resource.thread_id, + }, + {}, + context, + ); + + if (e.resource.ephemeral) { + await this.channelViewProcessor.process(thread || null, e); + return; + } await this.channelViewProcessor.process(thread, e); await this.channelMarkedViewProcessor.process(thread, e); @@ -63,6 +61,7 @@ export class MessagesEngine implements Initializable { await this.userMarkedViewProcessor.process(thread, e); await this.filesViewProcessor.process(thread, e); await this.messageToNotifications.process(thread, e); + await this.messageToHooks.process(thread, e); if (e.created) { for (const workspaceId of _.uniq( @@ -81,20 +80,33 @@ export class MessagesEngine implements Initializable { } async init(): Promise { - this.threadRepository = await this.database.getRepository("threads", Thread); + this.threadRepository = await gr.database.getRepository("threads", Thread); + this.messageRepository = await gr.database.getRepository("messages", Message); await this.channelViewProcessor.init(); await this.channelMarkedViewProcessor.init(); await this.userInboxViewProcessor.init(); await this.userMarkedViewProcessor.init(); await this.filesViewProcessor.init(); - this.pubsub.processor.addHandler(new ChannelSystemActivityMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new StatisticsMessageProcessor(this.statistics)); + + gr.platformServices.messageQueue.processor.addHandler( + new ChannelSystemActivityMessageProcessor(), + ); + gr.platformServices.messageQueue.processor.addHandler(new StatisticsMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler( + new MessageLinksPreviewFinishedProcessor(this.messageRepository, this.threadRepository), + ); localEventBus.subscribe("message:saved", async (e: MessageLocalEvent) => { this.dispatchMessage(e); }); + localEventBus.subscribe("message:download", async (e: MessageFileDownloadEvent) => { + if (e.user?.id) { + await this.filesViewProcessor.processDownloaded(e.user?.id, e.operation); + } + }); + return this; } } diff --git a/twake/backend/node/src/services/messages/services/engine/processors/channel-marked/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/channel-marked/index.ts index 2659e492f5..cf341fa3fc 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/channel-marked/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/channel-marked/index.ts @@ -1,26 +1,28 @@ import { MessageLocalEvent } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; import { Thread } from "../../../../entities/threads"; import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; import { - MessageChannelMarkedRef, getInstance, + MessageChannelMarkedRef, } from "../../../../entities/message-channel-marked-refs"; +import gr from "../../../../../global-resolver"; +import { ExecutionContext } from "../../../../../../core/platform/framework/api/crud-service"; export class ChannelMarkedViewProcessor { repository: Repository; - constructor(readonly database: DatabaseServiceAPI, readonly service: MessageServiceAPI) {} - async init() { - this.repository = await this.database.getRepository( + this.repository = await gr.database.getRepository( "message_channel_marked_refs", MessageChannelMarkedRef, ); } - async process(thread: Thread, message: MessageLocalEvent): Promise { + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { for (const participant of thread.participants.filter(p => p.type === "channel")) { //Pinned messages const pinRef = getInstance({ @@ -34,9 +36,9 @@ export class ChannelMarkedViewProcessor { created_by: message.resource.pinned_info?.pinned_by || "", }); if (message.resource.pinned_info) { - this.repository.save(pinRef); + this.repository.save(pinRef, context); } else if (!message.created) { - this.repository.remove(pinRef); + this.repository.remove(pinRef, context); } //TODO add realtime diff --git a/twake/backend/node/src/services/messages/services/engine/processors/channel-view/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/channel-view/index.ts index 8a72c6c523..b0d28b4860 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/channel-view/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/channel-view/index.ts @@ -1,14 +1,12 @@ import { MessageLocalEvent, ThreadExecutionContext } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; -import { Thread } from "../../../../entities/threads"; +import { ParticipantObject, Thread } from "../../../../entities/threads"; import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; import { getInstance, MessageChannelRef } from "../../../../entities/message-channel-refs"; import { getInstance as getInstanceReversed, MessageChannelRefReversed, } from "../../../../entities/message-channel-refs-reversed"; -import { localEventBus } from "../../../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../../../core/platform/framework/event-bus"; import { RealtimeEntityActionType, RealtimeLocalBusEvent, @@ -17,32 +15,49 @@ import { import { Message } from "../../../../entities/messages"; import { CreateResult, + ExecutionContext, UpdateResult, } from "../../../../../../core/platform/framework/api/crud-service"; import { getThreadMessagePath } from "../../../../web/realtime"; -import fetch from "node-fetch"; -import config from "config"; -import { logger } from "../../../../../../core/platform/framework"; +import gr from "../../../../../global-resolver"; +import { publishMessageInRealtime } from "../../../utils"; export class ChannelViewProcessor { repository: Repository; repositoryReversed: Repository; - constructor(readonly database: DatabaseServiceAPI, readonly service: MessageServiceAPI) {} - async init() { - this.repository = await this.database.getRepository( + this.repository = await gr.database.getRepository( "message_channel_refs", MessageChannelRef, ); - this.repositoryReversed = await this.database.getRepository( + this.repositoryReversed = await gr.database.getRepository( "message_channel_refs_reversed", MessageChannelRefReversed, ); } - async process(thread: Thread, message: MessageLocalEvent): Promise { - for (const participant of (thread.participants || []).filter(p => p.type === "channel")) { + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { + let participants: ParticipantObject[] = thread?.participants || []; + + if (participants.length === 0) { + participants = message.context.channel + ? [ + { + type: "channel", + id: message.context.channel.id, + workspace_id: message.context.workspace.id, + company_id: message.context.company.id, + } as ParticipantObject, + ] + : []; + } + + for (const participant of (participants || []).filter(p => p.type === "channel")) { if (!message.resource.ephemeral) { //Publish message in corresponding channel if (message.created) { @@ -53,10 +68,14 @@ export class ChannelViewProcessor { }; //If a pointer exists it means the message already exists (it was probably moved and so we need to keep everything in place) - const existingPointer = await this.repository.findOne({ - ...pkPrefix, - message_id: message.resource.id, - }); + const existingPointer = await this.repository.findOne( + { + ...pkPrefix, + message_id: message.resource.id, + }, + {}, + context, + ); if (!existingPointer) { await this.repository.save( @@ -65,25 +84,34 @@ export class ChannelViewProcessor { thread_id: thread.id, message_id: message.resource.id, }), + context, ); - const reversed = await this.repositoryReversed.findOne({ - ...pkPrefix, - thread_id: thread.id, - }); + const reversed = await this.repositoryReversed.findOne( + { + ...pkPrefix, + thread_id: thread.id, + }, + {}, + context, + ); if (reversed) { - const existingThreadRef = await this.repository.findOne({ - ...pkPrefix, - message_id: reversed.message_id, - }); + const existingThreadRef = await this.repository.findOne( + { + ...pkPrefix, + message_id: reversed.message_id, + }, + {}, + context, + ); if ( existingThreadRef && `${existingThreadRef.thread_id}` === `${message.resource.thread_id}` ) { reversed.message_id = message.resource.id; - await this.repositoryReversed.save(reversed); - await this.repository.remove(existingThreadRef); + await this.repositoryReversed.save(reversed, context); + await this.repository.remove(existingThreadRef, context); } } else { await this.repositoryReversed.save( @@ -92,6 +120,7 @@ export class ChannelViewProcessor { thread_id: thread.id, message_id: message.resource.id, }), + context, ); } } @@ -104,6 +133,7 @@ export class ChannelViewProcessor { thread_id: thread.id, message_id: message.resource.id, }), + context, ); await this.repositoryReversed.save( getInstanceReversed({ @@ -111,50 +141,14 @@ export class ChannelViewProcessor { thread_id: thread.id, message_id: message.resource.id, }), + context, ); } } } - if (process.env.NODE_ENV !== "cli") { - logger.debug("Share with php realtime endpoint: " + config.get("phpnode.php_endpoint")); - //Monkey patch to remove as soon as nobody use php depreciated endpoints - if (config.get("phpnode.php_endpoint")) { - fetch(config.get("phpnode.php_endpoint") + "/ajax/discussion/noderealtime", { - method: "POST", - headers: { - Authorization: "Token " + config.get("phpnode.secret"), - "Content-Type": "application/json", - Accept: "application/json", - }, - body: JSON.stringify({ - entity: message.resource, - context: message.context, - participant: participant, - }), - }); - } - } - //Publish message in realtime - const room = `/companies/${participant.company_id}/workspaces/${participant.workspace_id}/channels/${participant.id}/feed`; - const type = "message"; - const entity = message.resource; - const context = message.context; - localEventBus.publish("realtime:publish", { - topic: message.created - ? RealtimeEntityActionType.Created - : RealtimeEntityActionType.Updated, - event: { - type: type, - room: ResourcePath.get(room), - resourcePath: getThreadMessagePath(context as ThreadExecutionContext) + "/" + entity.id, - entity: entity, - result: message.created - ? new CreateResult(type, entity) - : new UpdateResult(type, entity), - }, - } as RealtimeLocalBusEvent); + publishMessageInRealtime(message, participant); } } } diff --git a/twake/backend/node/src/services/messages/services/engine/processors/files/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/files/index.ts index 4fa36027ad..01920e691c 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/files/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/files/index.ts @@ -1,23 +1,86 @@ import { MessageLocalEvent } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; import { Thread } from "../../../../entities/threads"; import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; import { getInstance, MessageFileRef } from "../../../../entities/message-file-refs"; +import gr from "../../../../../global-resolver"; +import uuid from "node-uuid"; +import { + ExecutionContext, + Pagination, +} from "../../../../../../core/platform/framework/api/crud-service"; +import { MessageFile } from "../../../../entities/message-files"; +import { fileIsMedia } from "../../../../../files/utils"; export class FilesViewProcessor { repository: Repository; - - constructor(readonly database: DatabaseServiceAPI, readonly service: MessageServiceAPI) {} + messageFileRepository: Repository; async init() { - this.repository = await this.database.getRepository( + this.repository = await gr.database.getRepository( "message_file_refs", MessageFileRef, ); + this.messageFileRepository = await gr.database.getRepository( + "message_files", + MessageFile, + ); + } + + async processDownloaded( + userId: string, + operation: { message_id: string; thread_id: string; message_file_id: string }, + context?: ExecutionContext, + ): Promise { + const messageFile = await this.messageFileRepository.findOne( + { + message_id: operation.message_id, + id: operation.message_file_id, + }, + {}, + context, + ); + + const thread = await gr.services.messages.threads.get( + { + id: operation.thread_id, + }, + context, + ); + + const refs = await this.repository.find( + { target_type: "user_download", target_id: userId, company_id: messageFile.company_id }, + { + pagination: new Pagination("", "100"), + }, + context, + ); + if (refs.getEntities().some(r => r.message_file_id === messageFile.id)) { + //File already in the recent list + return; + } + + //For the user we add it as downloaded by user + const fileRef = getInstance({ + target_type: "user_download", + target_id: userId, + id: uuid.v1(), + created_at: new Date().getTime(), + file_id: messageFile?.metadata?.external_id, + company_id: messageFile.company_id, + workspace_id: thread.participants?.find(p => p.type === "channel")?.workspace_id || "", + channel_id: thread.participants?.find(p => p.type === "channel")?.id || "", + thread_id: messageFile.thread_id, + message_id: messageFile.message_id, + message_file_id: messageFile.id, + }); + this.repository.save(fileRef, context); } - async process(thread: Thread, message: MessageLocalEvent): Promise { + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { if (!message.resource.ephemeral) { for (const file of message.resource.files || []) { //For each channel, we add the media @@ -25,30 +88,56 @@ export class FilesViewProcessor { const fileRef = getInstance({ target_type: "channel", target_id: participant.id, - id: file.id, + id: uuid.v1(), created_at: message.resource.created_at, workspace_id: participant.workspace_id, channel_id: participant.id, thread_id: thread.id, message_id: message.resource.id, - file_id: file.id, + message_file_id: file.id, + company_id: file.company_id, + file_id: file.metadata.external_id, }); - this.repository.save(fileRef); + this.repository.save(fileRef, context); + + const isMedia = fileIsMedia(file); + for (const type of [ + "channel", + isMedia ? "channel_media" : "channel_file", + ] as MessageFileRef["target_type"][]) { + const fileRef = getInstance({ + target_type: type, + target_id: participant.id, + id: uuid.v1(), + created_at: message.resource.created_at, + workspace_id: participant.workspace_id, + channel_id: participant.id, + thread_id: thread.id, + message_id: message.resource.id, + message_file_id: file.id, + company_id: file.company_id, + file_id: file.metadata.external_id, + }); + this.repository.save(fileRef); + } } //For the user we add it as uploaded by user const fileRef = getInstance({ target_type: "user_upload", target_id: message.resource.user_id, - id: file.id, + id: uuid.v1(), created_at: message.resource.created_at, - workspace_id: "", - channel_id: "", + workspace_id: + (thread.participants || []).filter(p => p.type === "channel")[0]?.workspace_id || "", + channel_id: (thread.participants || []).filter(p => p.type === "channel")[0]?.id || "", thread_id: thread.id, message_id: message.resource.id, - file_id: file.id, + message_file_id: file.id, + company_id: file.company_id, + file_id: file.metadata.external_id, }); - this.repository.save(fileRef); + this.repository.save(fileRef, context); } } } diff --git a/twake/backend/node/src/services/messages/services/engine/processors/links/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/links/index.ts new file mode 100644 index 0000000000..4855751eba --- /dev/null +++ b/twake/backend/node/src/services/messages/services/engine/processors/links/index.ts @@ -0,0 +1,85 @@ +import { logger, TwakeContext } from "../../../../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../../../../core/platform/services/message-queue/api"; +import { Message } from "../../../../entities/messages"; +import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; +import { LinkPreviewMessageQueueCallback } from "../../../../../previews/types"; +import { Thread } from "../../../../entities/threads"; +import { publishMessageInRealtime } from "../../../utils"; +import { ExecutionContext } from "../../../../../../core/platform/framework/api/crud-service"; + +export class MessageLinksPreviewFinishedProcessor + implements MessageQueueHandler +{ + constructor( + private MessageRepository: Repository, + private ThreadRepository: Repository, + ) {} + readonly name = "MessageLinksPreviewFinishedProcessor"; + readonly topics = { + in: "services:preview:links:callback", + }; + + readonly options = { + unique: true, + ack: true, + }; + + init?(context?: TwakeContext): Promise { + throw new Error("Method not implemented."); + } + + validate(message: LinkPreviewMessageQueueCallback): boolean { + return !!(message && message.previews && message.previews.length); + } + + async process( + localMessage: LinkPreviewMessageQueueCallback, + context?: ExecutionContext, + ): Promise { + logger.info( + `${this.name} - updating message links with generated previews: ${localMessage.previews.length}`, + ); + + const entity = await this.MessageRepository.findOne( + { + thread_id: localMessage.message.resource.thread_id, + id: localMessage.message.resource.id, + }, + {}, + context, + ); + + if (!entity) { + logger.error(`${this.name} - message not found`); + return ""; + } + + entity.links = localMessage.previews; + + await this.MessageRepository.save(entity, context); + + const thread: Thread = await this.ThreadRepository.findOne( + { + id: localMessage.message.resource.thread_id, + }, + {}, + context, + ); + + if (!thread) { + logger.error(`${this.name} - thread not found`); + return ""; + } + + const updatedMessage = { + ...localMessage.message, + resource: entity, + }; + + for (const participant of thread.participants.filter(p => p.type === "channel")) { + publishMessageInRealtime(updatedMessage, participant); + } + + return "done"; + } +} diff --git a/twake/backend/node/src/services/messages/services/engine/processors/message-to-hooks/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/message-to-hooks/index.ts new file mode 100644 index 0000000000..12f92bf7e6 --- /dev/null +++ b/twake/backend/node/src/services/messages/services/engine/processors/message-to-hooks/index.ts @@ -0,0 +1,107 @@ +import { MessageHook, MessageLocalEvent } from "../../../../types"; +import { ParticipantObject, Thread } from "../../../../entities/threads"; +import { logger } from "../../../../../../core/platform/framework"; +import { Channel } from "../../../../../channels/entities"; +import { + ExecutionContext, + Pagination, +} from "../../../../../../core/platform/framework/api/crud-service"; +import { Message } from "../../../../entities/messages"; +import gr from "../../../../../global-resolver"; + +export class MessageToHooksProcessor { + private name = "MessageToHooksProcessor"; + + async init() { + return this; + } + + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { + logger.debug(`${this.name} - Share message with channel microservice for hooks`); + + if (message.resource.ephemeral) { + logger.debug(`${this.name} - Cancel because message is ephemeral`); + return; + } + + try { + const messageResource = message.resource; + + for (const participant of thread.participants) { + if (participant.type !== "channel") { + continue; + } + + const channel: Channel = await gr.services.channels.channels.get( + { + id: participant.id, + company_id: participant.company_id, + workspace_id: participant.workspace_id, + }, + context, + ); + + if (!channel) { + continue; + } + + for (const appId of channel.connectors) { + if (message.resource.application_id !== appId) { + //Publish hook + await gr.platformServices.messageQueue.publish( + "application:hook:message", + { + data: { + type: "message", + application_id: appId, + company_id: participant.company_id, + channel: channel, + thread: thread, + message: messageResource, + }, + }, + ); + } + } + } + } catch (err) { + logger.warn({ err }, `${this.name} - Error while publishing`); + } + } + + async isLastActivityMessageDeleted( + participant: ParticipantObject, + messageResource: Message, + message: MessageLocalEvent, + ): Promise { + if (participant.company_id && participant.workspace_id && participant.id) { + const list = await gr.services.messages.views.listChannel( + new Pagination("", "1"), + { + include_users: false, + replies_per_thread: 1, + emojis: false, + }, + { + channel: { + company_id: participant.company_id, + workspace_id: participant.workspace_id, + id: participant.id, + }, + user: { + id: messageResource.user_id, + }, + }, + ); + + return ( + list.getEntities().pop()?.id === message.resource.id && + messageResource.subtype === "deleted" + ); + } + } +} diff --git a/twake/backend/node/src/services/messages/services/engine/processors/message-to-notifications/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/message-to-notifications/index.ts index 0d5adc3d72..54fc45c4b4 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/message-to-notifications/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/message-to-notifications/index.ts @@ -1,30 +1,29 @@ -import { MessageLocalEvent, MessageNotification, specialMention } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; -import { Thread } from "../../../../entities/threads"; +import { MessageLocalEvent, MessageNotification } from "../../../../types"; +import { ParticipantObject, Thread } from "../../../../entities/threads"; import { logger } from "../../../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../../../core/platform/services/pubsub/api"; import { Channel } from "../../../../../channels/entities"; import { isDirectChannel } from "../../../../../channels/utils"; import { ChannelActivityNotification } from "../../../../../channels/types"; -import UserServiceAPI from "../../../../../user/api"; -import ChannelServiceAPI from "../../../../../channels/provider"; import { getMentions } from "../../../utils"; +import { + ExecutionContext, + Pagination, +} from "../../../../../../core/platform/framework/api/crud-service"; +import { Message } from "../../../../../../services/messages/entities/messages"; +import gr from "../../../../../global-resolver"; export class MessageToNotificationsProcessor { private name = "MessageToNotificationsProcessor"; - constructor( - readonly database: DatabaseServiceAPI, - private pubsub: PubsubServiceAPI, - private user: UserServiceAPI, - private channels: ChannelServiceAPI, - readonly service: MessageServiceAPI, - ) {} - - async init() {} + async init() { + // + } - async process(thread: Thread, message: MessageLocalEvent): Promise { + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { logger.debug(`${this.name} - Share message with notification microservice`); if (message.resource.ephemeral) { @@ -40,50 +39,47 @@ export class MessageToNotificationsProcessor { continue; } - const channel: Channel = await this.channels.channels.get( + const channel: Channel = await gr.services.channels.channels.get( { id: participant.id, company_id: participant.company_id, workspace_id: participant.workspace_id, }, - { - user: { server_request: true, id: null }, - workspace: { - company_id: participant.company_id, - workspace_id: participant.workspace_id, - }, - }, + context, ); if (!channel) { continue; } - const company = await this.user.companies.getCompany({ id: participant.company_id }); + const company = await gr.services.companies.getCompany({ id: participant.company_id }); - let companyName = company?.name || ""; + const companyName = company?.name || ""; let workspaceName = ""; let senderName = "Twake"; if (messageResource.user_id) { - const user = await this.user.users.get({ id: messageResource.user_id }); + const user = await gr.services.users.get({ id: messageResource.user_id }); senderName = - `${user?.first_name} ${user?.last_name}`.trim() || `@${user?.username_canonical}`; + `${user?.first_name || ""} ${user?.last_name || ""}`.trim() || + `@${user?.username_canonical}`; } let title = ""; let text = (messageResource.text || "").substr(0, 255); - let body = messageResource.text; // we need original body just in case text gets updated further on + const body = messageResource.text; // we need original body just in case text gets updated further on if (isDirectChannel(channel)) { title = `${senderName} in ${companyName}`; } else { const workspace = - (await this.user.companies.getCompany({ id: participant.workspace_id })) || null; + (await gr.services.companies.getCompany({ id: participant.workspace_id })) || null; workspaceName = workspace?.name || workspaceName; title = `${channel.name} in ${companyName} • ${workspaceName}`; text = `${senderName}: ${text}`; } - const mentions = getMentions(messageResource); + const mentions = await getMentions(messageResource, async (username: string) => { + return await gr.services.users.getByUsername(username); + }); const messageEvent: MessageNotification = { company_id: participant.company_id, @@ -122,14 +118,19 @@ export class MessageToNotificationsProcessor { `${this.name} - Forward message ${messageResource.id} to channel:activity and message:created / message:updated`, ); - //Ignore system messages - if (message.created) { - await this.pubsub.publish("channel:activity", { - data: channelEvent, - }); + if ( + message.created || + (await this.isLastActivityMessageDeleted(participant, messageResource, message)) + ) { + await gr.platformServices.messageQueue.publish( + "channel:activity", + { + data: channelEvent, + }, + ); } - await this.pubsub.publish( + await gr.platformServices.messageQueue.publish( message.created ? "message:created" : "message:updated", { data: messageEvent, @@ -143,4 +144,36 @@ export class MessageToNotificationsProcessor { logger.warn({ err }, `${this.name} - Error while publishing`); } } + + async isLastActivityMessageDeleted( + participant: ParticipantObject, + messageResource: Message, + message: MessageLocalEvent, + ): Promise { + if (participant.company_id && participant.workspace_id && participant.id) { + const list = await gr.services.messages.views.listChannel( + new Pagination("", "1"), + { + include_users: false, + replies_per_thread: 1, + emojis: false, + }, + { + channel: { + company_id: participant.company_id, + workspace_id: participant.workspace_id, + id: participant.id, + }, + user: { + id: messageResource.user_id, + }, + }, + ); + + return ( + list.getEntities().pop()?.id === message.resource.id && + messageResource.subtype === "deleted" + ); + } + } } diff --git a/twake/backend/node/src/services/messages/services/engine/processors/system-activity-message/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/system-activity-message/index.ts index bcb5f13463..1c44a3f02b 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/system-activity-message/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/system-activity-message/index.ts @@ -1,14 +1,13 @@ -import { MessageServiceAPI } from "../../../../api"; -import { PubsubHandler } from "../../../../../../core/platform/services/pubsub/api"; +import { MessageQueueHandler } from "../../../../../../core/platform/services/message-queue/api"; import { ActivityPublishedType } from "../../../../../channels/services/channel/activities/types"; import { ParticipantObject } from "../../../../entities/threads"; import { getInstance } from "../../../../entities/messages"; import { logger } from "../../../../../../core/platform/framework"; +import gr from "../../../../../global-resolver"; export class ChannelSystemActivityMessageProcessor - implements PubsubHandler { - constructor(readonly service: MessageServiceAPI) {} - + implements MessageQueueHandler +{ readonly topics = { in: "channel:activity_message", }; @@ -47,14 +46,13 @@ export class ChannelSystemActivityMessageProcessor }, ]; - this.service.threads.save( + gr.services.messages.threads.save( { id: undefined, participants, }, { message, - participants, }, { user: { diff --git a/twake/backend/node/src/services/messages/services/engine/processors/user-inbox/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/user-inbox/index.ts index a262232f26..4bcf8d1140 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/user-inbox/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/user-inbox/index.ts @@ -1,47 +1,50 @@ import { MessageLocalEvent, ThreadExecutionContext } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; import { Thread } from "../../../../entities/threads"; import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; import { - MessageUserInboxRef, getInstance as getInboxRefInstance, + MessageUserInboxRef, } from "../../../../entities/message-user-inbox-refs"; import { - MessageUserInboxRefReversed, getInstance as getInboxThreadInstance, + MessageUserInboxRefReversed, } from "../../../../entities/message-user-inbox-refs-reversed"; -import { localEventBus } from "../../../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../../../core/platform/framework/event-bus"; import { RealtimeEntityActionType, RealtimeLocalBusEvent, + ResourcePath, } from "../../../../../../core/platform/services/realtime/types"; -import { ResourcePath } from "../../../../../../core/platform/services/realtime/types"; import { getThreadMessagePath } from "../../../../web/realtime"; import { CreateResult, + ExecutionContext, UpdateResult, } from "../../../../../../core/platform/framework/api/crud-service"; import { Message } from "../../../../entities/messages"; +import gr from "../../../../../global-resolver"; +import { publishMessageInRealtime } from "../../../utils"; export class UserInboxViewProcessor { repositoryRef: Repository; repositoryReversed: Repository; - constructor(readonly database: DatabaseServiceAPI, readonly service: MessageServiceAPI) {} - async init() { - this.repositoryRef = await this.database.getRepository( + this.repositoryRef = await gr.database.getRepository( "message_user_inbox_refs", MessageUserInboxRef, ); - this.repositoryReversed = await this.database.getRepository( + this.repositoryReversed = await gr.database.getRepository( "message_user_inbox_refs_reversed", MessageUserInboxRefReversed, ); } - async process(thread: Thread, message: MessageLocalEvent): Promise { + async process( + thread: Thread, + message: MessageLocalEvent, + context?: ExecutionContext, + ): Promise { for (const userParticipant of thread.participants.filter(p => p.type === "user")) { for (const channelParticipant of thread.participants.filter(p => p.type === "channel")) { //Publish message in corresponding channel @@ -57,14 +60,18 @@ export class UserInboxViewProcessor { thread_id: thread.id, }; - let threadActivityReversed = await this.repositoryReversed.findOne(commonPk); + let threadActivityReversed = await this.repositoryReversed.findOne(commonPk, {}, context); let currentRef: MessageUserInboxRef = null; if (threadActivityReversed) { - currentRef = await this.repositoryRef.findOne({ - ...commonPk, - last_activity: threadActivityReversed.last_activity, - }); + currentRef = await this.repositoryRef.findOne( + { + ...commonPk, + last_activity: threadActivityReversed.last_activity, + }, + {}, + context, + ); } else { threadActivityReversed = getInboxThreadInstance({ ...commonPk, @@ -80,34 +87,17 @@ export class UserInboxViewProcessor { }); if (currentRef) { - await this.repositoryReversed.remove(currentRef); + await this.repositoryReversed.remove(currentRef, context); } - await this.repositoryRef.save(ref); + await this.repositoryRef.save(ref, context); threadActivityReversed.last_activity = message.resource.created_at; - await this.repositoryReversed.save(threadActivityReversed); + await this.repositoryReversed.save(threadActivityReversed, context); } //Publish message in realtime //TODO send a thread object instead of a message object - const room = `/companies/${channelParticipant.company_id}/users/${userParticipant.id}/inbox`; - const type = "message"; - const entity = message.resource; - const context = message.context; - localEventBus.publish("realtime:publish", { - topic: message.created - ? RealtimeEntityActionType.Created - : RealtimeEntityActionType.Updated, - event: { - type: type, - room: ResourcePath.get(room), - resourcePath: getThreadMessagePath(context as ThreadExecutionContext) + "/" + entity.id, - entity: entity, - result: message.created - ? new CreateResult(type, entity) - : new UpdateResult(type, entity), - }, - } as RealtimeLocalBusEvent); + publishMessageInRealtime(message, channelParticipant); } } } diff --git a/twake/backend/node/src/services/messages/services/engine/processors/user-marked/index.ts b/twake/backend/node/src/services/messages/services/engine/processors/user-marked/index.ts index 217aa5a658..61351f2f08 100644 --- a/twake/backend/node/src/services/messages/services/engine/processors/user-marked/index.ts +++ b/twake/backend/node/src/services/messages/services/engine/processors/user-marked/index.ts @@ -1,21 +1,20 @@ import { MessageLocalEvent } from "../../../../types"; -import { MessageServiceAPI } from "../../../../api"; -import { DatabaseServiceAPI } from "../../../../../../core/platform/services/database/api"; import { Thread } from "../../../../entities/threads"; import Repository from "../../../../../../core/platform/services/database/services/orm/repository/repository"; import { MessageUserMarkedRef } from "../../../../entities/message-user-marked_refs"; +import gr from "../../../../../global-resolver"; export class UserMarkedViewProcessor { repository: Repository; - constructor(readonly database: DatabaseServiceAPI, readonly service: MessageServiceAPI) {} - async init() { - this.repository = await this.database.getRepository( + this.repository = await gr.database.getRepository( "message_user_marked_refs", MessageUserMarkedRef, ); } - async process(thread: Thread, message: MessageLocalEvent): Promise {} + async process(thread: Thread, message: MessageLocalEvent): Promise { + // + } } diff --git a/twake/backend/node/src/services/messages/services/index.ts b/twake/backend/node/src/services/messages/services/index.ts deleted file mode 100644 index 5fc02a699f..0000000000 --- a/twake/backend/node/src/services/messages/services/index.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { TwakeContext } from "../../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; -import { - MessageUserBookmarksServiceAPI, - MessageThreadsServiceAPI, - MessageThreadMessagesServiceAPI, - MessageViewsServiceAPI, - MessageServiceAPI, -} from "../api"; - -import { getService as getMessageUserBookmarksServiceAPI } from "./user-bookmarks"; -import { getService as getMessageThreadsServiceAPI } from "./threads"; -import { getService as getMessageThreadMessagesServiceAPI } from "./messages"; -import { getService as getMessageViewsServiceAPI } from "./views"; -import { MessagesEngine } from "./engine"; -import UserServiceAPI from "../../user/api"; -import ChannelServiceAPI from "../../channels/provider"; -import { FileServiceAPI } from "../../files/api"; -import { ApplicationServiceAPI } from "../../applications/api"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; -import { StatisticsAPI } from "../../statistics/types"; - -export function getService( - platformServices: PlatformServicesAPI, - user: UserServiceAPI, - channel: ChannelServiceAPI, - files: FileServiceAPI, - applications: ApplicationServiceAPI, - statistics: StatisticsAPI, -): Service { - return new Service(platformServices, user, channel, files, applications, statistics); -} - -export default class Service implements MessageServiceAPI { - version: "1"; - userBookmarks: MessageUserBookmarksServiceAPI; - threads: MessageThreadsServiceAPI; - messages: MessageThreadMessagesServiceAPI; - views: MessageViewsServiceAPI; - engine: MessagesEngine; - statistics: StatisticsAPI; - - constructor( - platformServices: PlatformServicesAPI, - user: UserServiceAPI, - channel: ChannelServiceAPI, - files: FileServiceAPI, - applications: ApplicationServiceAPI, - statistics: StatisticsAPI, - ) { - this.userBookmarks = getMessageUserBookmarksServiceAPI(platformServices.database); - this.messages = getMessageThreadMessagesServiceAPI( - platformServices, - user, - channel, - files, - applications, - this, - ); - this.threads = getMessageThreadsServiceAPI(platformServices.database, this); - this.views = getMessageViewsServiceAPI(platformServices, this); - this.engine = new MessagesEngine( - platformServices.database, - platformServices.pubsub, - user, - channel, - this, - statistics, - ); - - this.statistics = statistics; - } - - async init(context: TwakeContext): Promise { - try { - await Promise.all([ - this.userBookmarks.init(context), - this.threads.init(context), - this.messages.init(context), - this.views.init(context), - this.engine.init(), - ]); - } catch (err) { - console.error("Error while initializing messages service", err); - } - return this; - } -} diff --git a/twake/backend/node/src/services/messages/services/messages-files.ts b/twake/backend/node/src/services/messages/services/messages-files.ts new file mode 100644 index 0000000000..943bd14be6 --- /dev/null +++ b/twake/backend/node/src/services/messages/services/messages-files.ts @@ -0,0 +1,173 @@ +import { Channel } from "../../../services/channels/entities"; +import { fileIsMedia } from "../../../services/files/utils"; +import { UserObject } from "../../../services/user/web/types"; +import { formatUser } from "../../../utils/users"; +import { Initializable } from "../../../core/platform/framework"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import gr from "../../../services/global-resolver"; +import { MessageFileRef, TYPE as TYPERef } from "../entities/message-file-refs"; +import { MessageFile, TYPE } from "../entities/message-files"; +import { Message } from "../entities/messages"; +import _ from "lodash"; + +export class MessagesFilesService implements Initializable { + version: "1"; + msgFilesRepository: Repository; + msgFilesRefRepository: Repository; + + constructor() {} + + async init() { + this.msgFilesRepository = await gr.database.getRepository(TYPE, MessageFile); + this.msgFilesRefRepository = await gr.database.getRepository(TYPERef, MessageFileRef); + return this; + } + + /** + * Delete a message file and test this files belongs to the right user + * @param message_id + * @param id + * @param user_id + * @returns + */ + async deleteMessageFile(message_id: string, id: string, user_id: string) { + const msgFile = await this.getMessageFile(message_id, id); + if (!msgFile) return null; + + if (msgFile.message.user_id !== user_id) return null; + + await this.msgFilesRepository.remove(msgFile); + + for (const target_type of ["channel_media", "channel_file", "channel"]) { + const ref = await this.msgFilesRefRepository.findOne({ + target_type, + company_id: msgFile.channel.company_id, + target_id: msgFile.channel.id, + id: msgFile.id, + }); + if (ref) await this.msgFilesRefRepository.remove(ref); + } + + return msgFile; + } + + /** + * Get a message file and returns more contextual data + * @param message_id + * @param id + * @returns + */ + async getMessageFile( + message_id: string, + id: string, + ): Promise< + MessageFile & { + user: UserObject; + message: Message; + channel: Channel; + navigation: { next: Partial; previous: Partial }; + } + > { + const msgFile = await this.msgFilesRepository.findOne({ message_id, id }); + if (!msgFile) return null; + + const message = await gr.services.messages.messages.get({ + thread_id: msgFile.thread_id, + id: message_id, + }); + const channel = await gr.services.channels.channels.get({ + company_id: message.cache.company_id, + workspace_id: message.cache.workspace_id, + id: message.cache.channel_id, + }); + const user = await formatUser(await gr.services.users.get({ id: message.user_id })); + + const navigationPk = { + target_type: fileIsMedia(msgFile) ? "channel_media" : "channel_file", + company_id: channel.company_id, + target_id: channel.id, + }; + const { previous, next } = await this.getMessageFileNavigation(navigationPk, msgFile.id); + + return { + ...msgFile, + user, + message, + channel, + navigation: { + next: next + ? { + id: next.message_file_id, + message_id: next.message_id, + } + : null, + previous: previous + ? { + id: previous.message_file_id, + message_id: previous.message_id, + } + : null, + }, + }; + } + + /** + * Message file references are ordered with an id based on the time the file was uploaded + * We cannot get this specific ID directly from the message file right now + */ + private async getMessageFileNavigation( + navigationPk: { target_type: string; company_id: string; target_id: string }, + id: string, + ) { + const list = [ + ...( + await this.msgFilesRefRepository.find(navigationPk, { + pagination: { + page_token: null, + limitStr: "5", + reversed: false, + }, + $gte: [["id", id]], + }) + ).getEntities(), + ...( + await this.msgFilesRefRepository.find(navigationPk, { + pagination: { + page_token: null, + limitStr: "5", + reversed: true, + }, + $lte: [["id", id]], + }) + ).getEntities(), + ]; + const offsetRef = list.find(a => a.message_file_id === id) || null; + + let next = ( + await this.msgFilesRefRepository.find(navigationPk, { + pagination: { + page_token: null, + limitStr: "2", + reversed: true, + }, + $gte: [["id", offsetRef?.id || id]], + }) + ) + .getEntities() + .filter(a => a.message_file_id !== id)?.[0]; + let previous = ( + await this.msgFilesRefRepository.find(navigationPk, { + pagination: { + page_token: null, + limitStr: "2", + reversed: false, + }, + $lte: [["id", offsetRef?.id || id]], + }) + ) + .getEntities() + .filter(a => a.message_file_id !== id)?.[0]; + + return { previous, next }; + } +} diff --git a/twake/backend/node/src/services/messages/services/messages-operations.ts b/twake/backend/node/src/services/messages/services/messages-operations.ts new file mode 100644 index 0000000000..a635331108 --- /dev/null +++ b/twake/backend/node/src/services/messages/services/messages-operations.ts @@ -0,0 +1,301 @@ +import { OperationType, SaveResult } from "../../../core/platform/framework/api/crud-service"; +import { logger, TwakeContext } from "../../../core/platform/framework"; +import { Message, TYPE as MessageTableName } from "../entities/messages"; +import { + BookmarkOperation, + DeleteLinkOperation, + MessageFileDownloadEvent, + PinOperation, + ReactionOperation, + ThreadExecutionContext, + UpdateDeliveryStatusOperation, +} from "../types"; +import emoji from "emoji-name-map"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { ThreadMessagesService } from "./messages"; +import gr from "../../global-resolver"; +import { updateMessageReactions } from "../../../utils/messages"; +import { localEventBus } from "../../../core/platform/framework/event-bus"; +import { ReactionNotification } from "../../../services/notifications/types"; +export class ThreadMessagesOperationsService { + constructor(private threadMessagesService: ThreadMessagesService) {} + repository: Repository; + + async init(context: TwakeContext): Promise { + this.repository = await gr.database.getRepository(MessageTableName, Message); + return this; + } + + async pin( + operation: PinOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + if ( + !context?.user?.server_request && + !gr.services.messages.threads.checkAccessToThread(context) + ) { + logger.error(`Unable to write in thread ${context.thread.id}`); + throw Error("Can't edit this message."); + } + + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: operation.id, + }, + {}, + context, + ); + + if (!message) { + logger.error("This message doesn't exists"); + throw Error("Can't edit this message."); + } + + message.pinned_info = operation.pin + ? { + pinned_by: context.user.id, + pinned_at: new Date().getTime(), + } + : null; + + logger.info( + `Updated message ${operation.id} pin to ${JSON.stringify(message.pinned_info)} thread ${ + message.thread_id + }`, + ); + await this.repository.save(message, context); + this.threadMessagesService.onSaved(message, { created: false }, context); + return new SaveResult("message", message, OperationType.UPDATE); + } + + async reaction( + operation: ReactionOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + if ( + !context?.user?.server_request && + !gr.services.messages.threads.checkAccessToThread(context) + ) { + logger.error(`Unable to write in thread ${context.thread.id}`); + throw Error("Can't edit this message."); + } + + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: operation.id, + }, + {}, + context, + ); + + if (!message) { + logger.error("This message doesn't exists"); + throw Error("Can't edit this message."); + } + + //Update message reactions + updateMessageReactions(message, operation.reactions || [], context.user.id); + + logger.info( + `Updated message ${operation.id} reactions to ${JSON.stringify(message.reactions)} thread ${ + message.thread_id + }`, + ); + await this.repository.save(message, context); + + if ((operation.reactions || []).length === 1 && context.user.id !== message.user_id) { + await gr.platformServices.messageQueue.publish( + "notification:reaction", + { + data: { + thread_id: context.thread.id, + company_id: message.cache?.company_id || context.company.id, + user_id: message.user_id, + message_id: message.id, + workspace_id: message.cache?.workspace_id, + channel_id: message.cache?.channel_id, + creation_date: new Date().getTime(), + reaction: emoji.get(operation.reactions[0]), + reaction_user_id: context.user.id, + }, + }, + ); + } + + this.threadMessagesService.onSaved(message, { created: false }, context); + return new SaveResult("message", message, OperationType.UPDATE); + } + + async bookmark( + operation: BookmarkOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: operation.id, + }, + {}, + context, + ); + + if (!message) { + logger.error("This message doesn't exists"); + throw Error("Can't edit this message."); + } + + //TODO add message to user bookmarks + message.bookmarks = message.bookmarks.filter( + b => !(b.user_id === context.user.id && b.bookmark_id === operation.bookmark_id), + ); + if (operation.active) { + message.bookmarks.push({ + user_id: context.user.id, + bookmark_id: operation.bookmark_id, + created_at: new Date().getTime(), + }); + } + + logger.info( + `Added bookmark to message ${operation.id} => ${JSON.stringify( + message.bookmarks, + )} to thread ${message.thread_id}`, + ); + await this.repository.save(message, context); + this.threadMessagesService.onSaved(message, { created: false }, context); + + return new SaveResult("message", message, OperationType.UPDATE); + } + + async download( + operation: { id: string; thread_id: string; message_file_id: string }, + options: Record, + context: ThreadExecutionContext, + ) { + //Register download action for reference + localEventBus.publish("message:download", { + user: context.user, + operation: { + message_id: operation.id, + thread_id: operation.thread_id, + message_file_id: operation.message_file_id, + }, + } as MessageFileDownloadEvent); + } + + /** + * Delete a link preview from a message + * + * @param {DeleteLinkOperation} operation - params of the operation + * @param {ThreadExecutionContext} context - Thread execution context + * @returns {Promise>} - Result of the operation + */ + async deleteLinkPreview( + operation: DeleteLinkOperation, + context: ThreadExecutionContext, + ): Promise> { + if ( + !context?.user?.server_request && + !gr.services.messages.threads.checkAccessToThread(context) + ) { + logger.error(`no access ${context.thread.id}`); + throw Error("can't remove link preview from message."); + } + + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: operation.message_id, + }, + {}, + context, + ); + + if (!message) { + logger.error("This message doesn't exists"); + throw Error("Can't edit message links previews."); + } + + if (context.user.id !== message.user_id) { + logger.error("You can't remove link preview from another user message."); + throw Error("Can't edit message links previews."); + } + + message.links = message.links.filter(({ url }: { url: string }) => url !== operation.link); + + await this.repository.save(message, context); + this.threadMessagesService.onSaved(message, { created: false }, context); + + return new SaveResult("message", message, OperationType.UPDATE); + } + + /** + * Update message delivery status operation + * + * @param {UpdateDeliveryStatusOperation} operation - the operation params + * @param {ThreadExecutionContext} context - Thread execution context + * @returns {Promise>} - Result of the operation + */ + async updateDeliveryStatus( + operation: UpdateDeliveryStatusOperation, + context: ThreadExecutionContext, + ): Promise> { + if ( + !context?.user?.server_request && + !gr.services.messages.threads.checkAccessToThread(context) + ) { + logger.error(`no access ${context.thread.id}`); + throw Error("can't update message delivery status."); + } + + if (!operation.message_id || !operation.status) { + logger.error("Invalid operation"); + throw Error("Invalid operation"); + } + + if (operation.status !== "delivered" && operation.status !== "read") { + logger.error("Invalid status"); + throw Error("Invalid status"); + } + + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: operation.message_id, + }, + {}, + context, + ); + + if (!message) { + logger.error("This message doesn't exists"); + throw Error("Can't update message delivery status."); + } + + if (operation.status === "delivered" && message.status === "delivered") { + logger.error("Message already delivered"); + return; + } + + if (operation.status === "read" && message.status === "read") { + logger.error("Message already read"); + return; + } + + if (operation.status === "delivered" && message.status === "read" && !operation.self_message) { + logger.error("Invalid operation"); + return; + } + + message.status = operation.status; + await this.repository.save(message, context); + this.threadMessagesService.onSaved(message, { created: false }, context); + + return new SaveResult("message", message, OperationType.UPDATE); + } +} diff --git a/twake/backend/node/src/services/messages/services/messages.ts b/twake/backend/node/src/services/messages/services/messages.ts new file mode 100644 index 0000000000..9df8456c5e --- /dev/null +++ b/twake/backend/node/src/services/messages/services/messages.ts @@ -0,0 +1,1039 @@ +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Paginable, + Pagination, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import { + Initializable, + logger, + RealtimeSaved, + TwakeContext, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { + getInstance, + Message, + MessageWithUsers, + TYPE as MessageTableName, +} from "../entities/messages"; +import { MessageFile, TYPE as MsgFileTableName } from "../entities/message-files"; +import { + BookmarkOperation, + CompanyExecutionContext, + DeleteLinkOperation, + MessageIdentifier, + MessagesGetThreadOptions, + MessagesSaveOptions, + MessageWithReplies, + MessageWithRepliesWithUsers, + PinOperation, + ReactionOperation, + ThreadExecutionContext, + UpdateDeliveryStatusOperation, +} from "../types"; +import _ from "lodash"; +import { getThreadMessagePath, getThreadMessageWebsocketRoom } from "../web/realtime"; +import { ThreadMessagesOperationsService } from "./messages-operations"; +import { Thread } from "../entities/threads"; +import { UserObject } from "../../user/web/types"; +import { formatUser } from "../../../utils/users"; +import gr from "../../global-resolver"; +import { getDefaultMessageInstance } from "../../../utils/messages"; +import { buildMessageListPagination, getLinks, getMentions } from "./utils"; +import { localEventBus } from "../../../core/platform/framework/event-bus"; +import { + KnowledgeGraphEvents, + KnowledgeGraphGenericEventPayload, +} from "../../../core/platform/services/knowledge-graph/types"; +import { MessageUserInboxRef } from "../entities/message-user-inbox-refs"; +import { MessageUserInboxRefReversed } from "../entities/message-user-inbox-refs-reversed"; +import { LinkPreviewMessageQueueRequest } from "../../../services/previews/types"; +import { Thumbnail } from "../../files/entities/file"; +import uuidTime from "uuid-time"; + +export class ThreadMessagesService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + msgFilesRepository: Repository; + operations: ThreadMessagesOperationsService; + private messageUserInboxRefsRepository: Repository; + private threadRepository: Repository; + + constructor() { + this.operations = new ThreadMessagesOperationsService(this); + } + + async init(context: TwakeContext): Promise { + this.repository = await gr.database.getRepository(MessageTableName, Message); + this.msgFilesRepository = await gr.database.getRepository( + MsgFileTableName, + MessageFile, + ); + this.messageUserInboxRefsRepository = await gr.database.getRepository( + "message_user_inbox_refs", + MessageUserInboxRef, + ); + + this.threadRepository = await gr.database.getRepository("threads", Thread); + await this.operations.init(context); + return this; + } + + /** + * Save a message + * The server / application / users can do different actions + * @param item + * @param options + * @param context + * @returns SaveResult + */ + async save( + item: Partial, + options?: MessagesSaveOptions, + context?: ThreadExecutionContext, + ): Promise> { + //This can come from: + // - Server want to change the message somehow (the message should already be formated) + // - Application change the message + // - User change its message + // - Pin / Reaction / Bookmark are *not* done here + + const serverRequest = context?.user?.server_request; + const applicationRequest = context?.user?.application_id; + let messageOwnerAndNotRemoved = true; + + item.thread_id = (serverRequest ? item.thread_id : null) || context.thread.id; + const pk = _.pick(item, "thread_id", "id"); + + let messageCreated = !pk.id; + + if (!item.ephemeral) { + if ( + !pk.thread_id || + (!serverRequest && !gr.services.messages.threads.checkAccessToThread(context)) + ) { + logger.error(`Unable to write in thread ${context.thread.id}`); + throw Error("Can't write this message."); + } + } else { + pk.id = undefined; + } + + let message = getDefaultMessageInstance(item, context); + if (pk.id) { + const existingMessage = await this.repository.findOne(pk, {}, context); + if (!existingMessage && !serverRequest) { + logger.error(`This message ${item.id} doesn't exists in thread ${item.thread_id}`); + throw Error("This message doesn't exists."); + } + if (existingMessage) { + message = existingMessage; + messageOwnerAndNotRemoved = + ((context.user?.id && message.user_id === context.user?.id) || + (context.user?.application_id && + message.application_id === context.user?.application_id)) && + message.subtype !== "deleted"; + + if (message.user_id === context.user?.id && context.user?.id) { + message.edited = { + edited_at: new Date().getTime(), + }; + } + } else { + messageCreated = true; + } + } + + const updatable: { [K in keyof Partial]: boolean } = { + ephemeral: serverRequest || messageOwnerAndNotRemoved, + subtype: serverRequest, + text: serverRequest || messageOwnerAndNotRemoved, + blocks: serverRequest || messageOwnerAndNotRemoved, + context: serverRequest || messageOwnerAndNotRemoved, + override: serverRequest || (messageOwnerAndNotRemoved && !!applicationRequest), + }; + Object.keys(updatable).forEach(k => { + if ((updatable as any)[k] && (item as any)[k] !== undefined) { + (message as any)[k] = (item as any)[k]; + } + }); + message = _.assign(message, pk); + + if (context.workspace && context.channel) { + message.cache = { + company_id: context.company.id, + workspace_id: context.workspace.id, + channel_id: context.channel.id, + }; + } + + if (!message.ephemeral) { + if (options.threadInitialMessage) { + message.id = message.thread_id; + } + + logger.info(`Saved message in thread ${message.thread_id}`); + await this.repository.save(message, context); + } else { + logger.info(`Did not save ephemeral message in thread ${message.thread_id}`); + } + + if (serverRequest || messageOwnerAndNotRemoved) { + message = await this.completeMessage( + message, + { files: item.files || message.files || [] }, + context, + ); + } + + await this.onSaved(message, { created: messageCreated }, context); + + if (messageCreated && context.channel) { + localEventBus.publish>( + KnowledgeGraphEvents.MESSAGE_CREATED, + { + id: message.id, + resource: message, + links: [{ relation: "parent", type: "channel", id: context.channel.id }], + }, + ); + } + + return new SaveResult( + "message", + message, + messageCreated ? OperationType.CREATE : OperationType.UPDATE, + ); + } + + /** + * Move a message from a thread to another + * @param item + * @param options + * @param context + * @returns + */ + async move( + pk: Pick, + options: { previous_thread: string }, + context: ThreadExecutionContext, + ): Promise { + logger.debug( + `Try to move message ${pk.id} from thread ${options.previous_thread} to thread ${context.thread.id}`, + ); + + if (options.previous_thread === context.thread.id) { + return; + } + + //Move replies if it was a thread head message + if (pk.id === options.previous_thread) { + let nextPage: Pagination = { limitStr: "100" }; + do { + const replies = await this.list( + nextPage, + {}, + { + user: { id: null, server_request: true }, + thread: { id: pk.id }, + company: { id: context.company.id }, + }, + ); + + for (const reply of replies.getEntities()) { + //Do not create an infinite loop + if (reply.id !== options.previous_thread) { + logger.debug( + `Try to move reply ${reply.id} to message ${pk.id} from thread ${reply.thread_id} to thread ${context.thread.id}`, + ); + + await gr.services.messages.messages.move( + { id: reply.id || undefined }, + { + previous_thread: reply.thread_id, + }, + context, + ); + } + } + + nextPage = replies.nextPage as Pagination; + } while (nextPage.page_token); + } + + const messageInOldThread = await this.repository.findOne( + { + thread_id: options.previous_thread, + id: pk.id, + }, + {}, + context, + ); + + if (!messageInOldThread) { + logger.error(`Unable to find message ${pk.id} in old thread ${context.thread.id}`); + throw Error("Can't move this message."); + } + + //Check new thread exists + let thread = await gr.services.messages.threads.get({ id: context.thread.id }, context); + if (!thread && `${context.thread.id}` === `${pk.id}`) { + logger.info("Create empty thread for message moved out of thread"); + const oldThread = await gr.services.messages.threads.get( + { id: options.previous_thread }, + context, + ); + const upgradedContext = _.cloneDeep(context); + upgradedContext.user.server_request = true; + thread = ( + await gr.services.messages.threads.save( + { + id: messageInOldThread.id, + participants: oldThread.participants, + }, + {}, + upgradedContext, + ) + )?.entity; + } + if (!thread) { + throw Error("Can't move this message to inexistent thread."); + } + + const messageInNewThread = _.cloneDeep(messageInOldThread); + messageInNewThread.thread_id = context.thread.id; + + await this.repository.save(messageInNewThread, context); + + await this.onSaved(messageInNewThread, { created: true }, context); + + await this.repository.remove(messageInOldThread, context); + await gr.services.messages.threads.addReply(messageInOldThread.thread_id, -1, context); + + logger.info( + `Moved message ${pk.id} from thread ${options.previous_thread} to thread ${context.thread.id}`, + ); + + return; + } + + async forceDelete(pk: Message, context?: ThreadExecutionContext): Promise> { + return this.delete(pk, context, true); + } + + async delete( + pk: Message, + context?: ThreadExecutionContext, + forceDelete: boolean = false, + ): Promise> { + if ( + !context?.user?.server_request && + !gr.services.messages.threads.checkAccessToThread(context) + ) { + logger.error(`Unable to write in thread ${context.thread.id}`); + throw Error("Can't edit this message."); + } + + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id: pk.id, + }, + {}, + context, + ); + + if (!message) { + logger.error( + "This message does not exists, only remove it on websockets (ephemeral message)", + ); + + const msg = getInstance({ + subtype: "deleted", + ...pk, + }); + + msg.ephemeral = pk.ephemeral || { + id: pk.id, + version: "", + recipient: "", + recipient_context_id: "", + }; + + await this.onSaved(msg, { created: false }, context); + + return new DeleteResult("message", msg, true); + } + + if ( + !context?.user?.server_request && + message.user_id !== context.user.id && + message.application_id !== context?.user?.application_id + ) { + logger.error("You have no right to delete this message"); + throw Error("Can't delete this message."); + } + + message.subtype = "deleted"; + message.blocks = []; + message.reactions = []; + message.text = "Deleted message"; + message.files = []; + + logger.info(`Deleted message ${pk.id} from thread ${message.thread_id}`); + await this.repository.save(message, context); + await this.onSaved(message, { created: false }, context); + + //Only server and application can definively remove a message + if ( + (forceDelete && (context.user.server_request || context.user.application_id)) || + message.application_id + ) { + await this.repository.remove(message, context); + } + + return new DeleteResult("message", message, true); + } + + async get( + pk: Pick, + context?: ThreadExecutionContext, + options?: { includeQuoteInMessage?: boolean }, + ): Promise { + const thread = await gr.services.messages.threads.get({ id: pk.id }, context); + let message; + if (thread) { + message = await this.getThread(thread, options, context); + } else { + message = await this.getSingleMessage(pk, options, context); + } + return message; + } + + private async getSingleMessage( + pk: Pick, + options?: { includeQuoteInMessage?: boolean }, + context?: ExecutionContext, + ) { + let message = await this.repository.findOne(pk, {}, context); + if (message) { + message = await this.completeMessage( + message, + { + files: message.files || [], + includeQuoteInMessage: options?.includeQuoteInMessage, + }, + context, + ); + } + return message; + } + + async getThread( + thread: Thread, + options: MessagesGetThreadOptions = {}, + context?: ExecutionContext, + ): Promise { + const lastRepliesUncompleted = ( + await this.repository.find( + { + thread_id: thread.id, + }, + { + pagination: new Pagination("", `${options?.replies_per_thread || 3}`, false), + }, + context, + ) + ).getEntities(); + + const lastReplies: Message[] = []; + for (const lastReply of lastRepliesUncompleted) { + if (lastReply) + lastReplies.push( + await this.completeMessage(lastReply, { files: lastReply.files || [] }, context), + ); + } + + const firstMessage = await this.getSingleMessage( + { + thread_id: thread.id, + id: thread.id, + }, + {}, + context, + ); + + return { + ...firstMessage, + stats: { + replies: lastReplies.length === 1 ? 1 : thread.answers, //This line ensure the thread can be deleted by user if there is no replies + last_activity: thread.last_activity, + }, + last_replies: lastReplies.sort((a, b) => a.created_at - b.created_at), + }; + } + + async list( + pagination: Paginable, + options?: ListOption, + context?: ThreadExecutionContext, + ): Promise> { + const list = await this.repository.find( + { thread_id: context.thread.id }, + buildMessageListPagination(Pagination.fromPaginable(pagination), "id"), + context, + ); + + //Get complete details about initial message + if ( + list + .getEntities() + .map(m => `${m.id}`) + .includes(`${context.thread.id}`) + ) { + const initialMessage = await this.get( + { thread_id: context.thread.id, id: context.thread.id }, + context, + ); + list.mapEntities((m: any) => { + if (`${m.id}` === `${initialMessage.id}`) { + return initialMessage; + } + return m; + }); + } + + const extendedList = []; + for (const m of list.getEntities()) { + extendedList.push(await this.completeMessage(m, {}, context)); + } + + return new ListResult("messages", extendedList, list.nextPage); + } + + async includeUsersInMessage( + message: Message, + context?: ExecutionContext, + ): Promise { + let ids: string[] = []; + if (message.user_id) ids.push(message.user_id); + if (message.pinned_info?.pinned_by) ids.push(message.pinned_info?.pinned_by); + const mentions = await getMentions(message, async (username: string) => { + return await gr.services.users.getByUsername(username); + }); + for (const mentionedUser of mentions.users) { + ids.push(mentionedUser); + } + ids = _.uniq(ids); + + const users: UserObject[] = []; + for (const id of ids) { + const user = await gr.services.users.getCached({ id }); + if (user) users.push(await formatUser(user)); + } + + let application = null; + if (message.application_id) { + application = await gr.services.applications.marketplaceApps.get( + { + id: message.application_id, + }, + context, + ); + } + + const messageWithUsers: MessageWithUsers = { ...message, users, application }; + + if (message.quote_message && (message.quote_message as any).id) { + messageWithUsers.quote_message = await this.includeUsersInMessage( + message.quote_message as any, + context, + ); + } + + return messageWithUsers; + } + + async includeUsersInMessageWithReplies( + message: MessageWithReplies, + context?: ExecutionContext, + ): Promise { + let last_replies = undefined; + for (const reply of message.last_replies || []) { + if (!last_replies) last_replies = []; + last_replies.push(await this.includeUsersInMessage(reply, context)); + } + + let highlighted_replies = undefined; + for (const reply of message.highlighted_replies || []) { + if (!highlighted_replies) highlighted_replies = []; + highlighted_replies.push(await this.includeUsersInMessage(reply, context)); + } + + let thread: MessageWithRepliesWithUsers = undefined; + if (message.thread) { + thread = await this.includeUsersInMessageWithReplies(message.thread, context); + } + + const messageWithUsers = { + ...message, + users: (await this.includeUsersInMessage(message, context)).users, + last_replies, + ...(highlighted_replies ? { highlighted_replies } : {}), + ...(thread ? { thread } : {}), + } as MessageWithRepliesWithUsers; + + return messageWithUsers; + } + + @RealtimeSaved((message, context) => [ + { + room: ResourcePath.get(getThreadMessageWebsocketRoom(context as ThreadExecutionContext)), + path: getThreadMessagePath(context as ThreadExecutionContext) + "/" + message.id, + }, + ]) + async onSaved( + message: Message, + options: { created?: boolean }, + context: ThreadExecutionContext, + ): Promise> { + if (options.created && !message.ephemeral) { + const messageLinks = getLinks(message); + + gr.platformServices.messageQueue.publish( + "services:preview:links", + { + data: { + links: messageLinks, + message: { + context, + resource: message, + created: options?.created, + }, + }, + }, + ); + + await gr.services.messages.threads.addReply(message.thread_id, 1, context); + try { + await gr.services.channels.members.setChannelMemberReadSections( + { + start: message.id, + end: message.id, + }, + { + ...context, + channel_id: message.cache.channel_id, + workspace_id: message.cache.workspace_id, + }, + ); + } catch (error) { + logger.error("failed to set read sections"); + } + } + + //Depreciated way of doing this was localEventBus.publish("message:saved") + await gr.services.messages.engine.dispatchMessage({ + resource: message, + context: context, + created: options.created, + }); + + return new SaveResult( + "message", + message, + options.created ? OperationType.CREATE : OperationType.UPDATE, + ); + } + + async pin( + operation: PinOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + return this.operations.pin(operation, options, context); + } + + async reaction( + operation: ReactionOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + return this.operations.reaction(operation, options, context); + } + + async bookmark( + operation: BookmarkOperation, + options: Record, + context: ThreadExecutionContext, + ): Promise> { + return this.operations.bookmark(operation, options, context); + } + + async download( + operation: { id: string; thread_id: string; message_file_id: string }, + options: Record, + context: ThreadExecutionContext, + ): Promise { + return this.operations.download(operation, options, context); + } + + //Complete message with all missing information and cache + async completeMessage( + message: Message, + options: { files?: Message["files"]; includeQuoteInMessage?: boolean } = {}, + context: ExecutionContext, + ) { + this.fixReactionsFormat(message, context); + try { + if (options.files) message = await this.completeMessageFiles(message, options.files || []); + } catch (err) { + console.log(err); + logger.warn("Error while completing message files"); + } + + //Mobile retro compatibility + if ((message.blocks?.length || 0) === 0) { + message.blocks = message.blocks || []; + message.blocks.push({ + type: "twacode", + elements: [message.text], + }); + } + + //Add quote message + if (options?.includeQuoteInMessage !== false) + message = await this.includeQuoteInMessage(message); + + return message; + } + + async includeQuoteInMessage(message: MessageWithUsers): Promise { + if (message.quote_message && (message.quote_message as Message["quote_message"]).id) { + message.quote_message = await this.includeUsersInMessage( + await this.getSingleMessage( + { + thread_id: (message.quote_message as Message["quote_message"]).thread_id, + id: (message.quote_message as Message["quote_message"]).id, + }, + { includeQuoteInMessage: false }, + ), + ); + } + return message; + } + + //Fix https://github.com/linagora/Twake/issues/1559 + async fixReactionsFormat(message: Message, context: ExecutionContext) { + if (message.reactions?.length > 0) { + let foundError = false; + message.reactions.map(r => { + if (!(r.users?.length > 0)) { + foundError = true; + r.users = Object.values(r.users); + } + }); + if (foundError) await this.repository.save(message, context); + } + } + + async completeMessageFiles( + message: Message, + files: Message["files"], + context?: ExecutionContext, + ) { + if (files.length === 0 && (message.files || []).length === 0) { + return message; + } + + let didChange = false; + + files = files.map(f => { + f.message_id = message.id; + return f; + }); + + const sameFile = (a: MessageFile["metadata"], b: MessageFile["metadata"]) => { + return _.isEqual(a.external_id, b.external_id) && a.source === b.source; + }; + + //Delete all existing msg files not in the new files object + const existingMsgFiles = ( + await this.msgFilesRepository.find( + { + message_id: message.id, + }, + {}, + context, + ) + ).getEntities(); + for (const entity of existingMsgFiles) { + if (!files.some(f => sameFile(f.metadata, entity.metadata))) { + await this.msgFilesRepository.remove(entity, context); + } + } + + //Ensure all files in the file object are in the message + const previousMessageFiles = message.files; + message.files = []; + for (const file of files) { + let existing = existingMsgFiles.filter(e => sameFile(e.metadata, file.metadata))[0]; + const entity = existing || new MessageFile(); + entity.message_id = message.id; + entity.thread_id = message.thread_id; + entity.id = file.id || undefined; + entity.company_id = file.company_id || message.cache?.company_id; + entity.cache = { + company_id: message.cache?.company_id, + workspace_id: message.cache?.workspace_id, + channel_id: message.cache?.channel_id, + user_id: message.user_id, + }; + entity.created_at = file.created_at || new Date().getTime(); + + //If it is defined it should exists + let messageFileExistOnDb = false; + try { + messageFileExistOnDb = !!(await this.msgFilesRepository.findOne( + { + message_id: message.id, + id: entity.id, + }, + {}, + context, + )); + } catch (e) {} + if (entity.id && !messageFileExistOnDb) { + existing = null; + entity.id = undefined; + } + + //For internal files, we have a special additional sync + if (file.metadata?.source == "internal") { + //Test external id format + if ( + message.files.length === 0 && + (typeof file.metadata.external_id === "string" || + !file.metadata.external_id?.company_id || + !file.metadata.external_id?.id) + ) { + console.log("File external_id format is wrong for source internal"); + continue; + } + + const original = await gr.services.files.get(file.metadata.external_id?.id as string, { + user: { id: "", server_request: true }, + company: { id: file.metadata.external_id?.company_id as string }, + }); + if (original) { + file.metadata = { + ...file.metadata, + ..._.pick(original.metadata, "mime", "name"), + ..._.pick(original.upload_data, "size"), + source: "internal", + external_id: file.metadata.external_id, + }; + file.metadata.thumbnails = (file.metadata.thumbnails || original.thumbnails || []).map( + (t: Thumbnail, index: number) => { + t.url = gr.services.files.getThumbnailRoute(original, (t.index || index).toString()); + return t; + }, + ); + } + } + + entity.metadata = file.metadata; + + if (!existing || !_.isEqual(existing.metadata, entity.metadata)) { + didChange = true; + await this.msgFilesRepository.save(entity, context); + } + + message.files.push(entity); + } + + if (!_.isEqual(previousMessageFiles.map(a => a.id).sort(), message.files.map(a => a.id).sort())) + didChange = true; + + if (didChange) { + await this.repository.save(message, context); + } + + return message; + } + + async inbox( + userId: string, + context: CompanyExecutionContext, + pagination: Pagination, + ): Promise> { + let nextPage = null; + + async function* getNextThreads( + refRepo: Repository, + ): AsyncIterableIterator { + let lastPageToken = pagination.page_token; + let hasMore = true; + do { + const threadsIds = await refRepo + .find( + { + company_id: context.company.id, + user_id: userId, + }, + { pagination: new Pagination(lastPageToken, pagination.limitStr) }, + context, + ) + .then((a: ListResult) => { + lastPageToken = a.nextPage.page_token; + nextPage = a.nextPage; + if (!lastPageToken) { + hasMore = false; + } + return a.getEntities().map(a => a.thread_id); + }); + + if (threadsIds.length) { + for (const threadId of threadsIds) { + yield threadId; + } + } else { + hasMore = false; + } + } while (hasMore); + } + + const threadsIds = []; + const threadsIdsMap: { [key: string]: boolean } = {}; + + for await (const id of getNextThreads(this.messageUserInboxRefsRepository)) { + if (!threadsIdsMap[id]) { + threadsIdsMap[id] = true; + threadsIds.push(id); + } + if (threadsIds.length == +pagination.limitStr) { + break; + } + } + + const msgPromises = threadsIds.map(id => + this.repository.findOne({ thread_id: id, id }, {}, context), + ); + return new ListResult("message", await Promise.all(msgPromises), nextPage); + } + + /** + * Deletes a link preview from message operation + * + * @param {DeleteLinkOperation} operation - The delete link operation + * @param {ThreadExecutionContext} context - The thread execution context + * @returns + */ + async deleteLinkPreview( + operation: DeleteLinkOperation, + context: ThreadExecutionContext, + ): Promise> { + return this.operations.deleteLinkPreview(operation, context); + } + + /** + * Updates the message delivery status to delivered or read. + * + * @param {UpdateDeliveryStatusOperation} operation - The update delivery status operation + * @param {ThreadExecutionContext} context - The thread execution context + * @returns {Promise>} - The save result + */ + async updateDeliveryStatus( + operation: UpdateDeliveryStatusOperation, + context: ThreadExecutionContext, + ): Promise> { + return this.operations.updateDeliveryStatus(operation, context); + } + + /** + * Updates the messages delivery status to read. + * + * @param {MessageReadType} messages - The messages to mark as read + * @param {CompanyExecutionContext & { channel_id: string; workspace_id: string }} context - The company execution context + * @returns {Promise} - The promise result of the operation + */ + async read( + messages: MessageIdentifier[], + context: CompanyExecutionContext & { channel_id: string; workspace_id: string }, + ): Promise { + const timestamps = messages + .map(({ message_id }) => ({ + message_id, + timestamp: uuidTime.v1(message_id), + })) + .sort((a, b) => a.timestamp - b.timestamp); + + const read_section = { + start: timestamps[0].message_id, + end: timestamps[timestamps.length - 1].message_id, + }; + + await gr.services.channels.members.setChannelMemberReadSections(read_section, context); + + const updates = await Promise.all( + messages.map(async message => { + const readOperation: UpdateDeliveryStatusOperation = { + ...message, + status: "read", + }; + + return this.updateDeliveryStatus(readOperation, { + ...context, + thread: { id: message.thread_id }, + }); + }), + ); + + return updates.every(item => !!item); + } + + /** + * List users who've seen the specified message + * + * @param { String} id - the message id + * @param {ThreadExecutionContext} context - the thread execution context + * @returns {Promise} - the users list + */ + async listSeenBy(id: string, context: ThreadExecutionContext): Promise { + try { + const message = await this.repository.findOne( + { + thread_id: context.thread.id, + id, + }, + {}, + context, + ); + + if (!message) { + logger.error(`message ${id} doesn't exist`); + throw Error("failed to list seen by users: message doesn't exist"); + } + + const channelContext = { + ...context, + channel: { + id: message.cache.channel_id, + company_id: context.company.id, + workspace_id: context.workspace.id, + }, + }; + + return await gr.services.channels.members.getChannelMessageSeenByUsers(id, channelContext); + } catch (error) { + logger.error(error); + return []; + } + } +} diff --git a/twake/backend/node/src/services/messages/services/messages/index.ts b/twake/backend/node/src/services/messages/services/messages/index.ts deleted file mode 100644 index f1b8eeb7cc..0000000000 --- a/twake/backend/node/src/services/messages/services/messages/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import ChannelServiceAPI from "../../../channels/provider"; -import UserServiceAPI from "../../../user/api"; -import { MessageServiceAPI, MessageThreadMessagesServiceAPI } from "../../api"; -import { ThreadMessagesService } from "./service"; -import { FileServiceAPI } from "../../../files/api"; -import { ApplicationServiceAPI } from "../../../applications/api"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - user: UserServiceAPI, - channel: ChannelServiceAPI, - files: FileServiceAPI, - applications: ApplicationServiceAPI, - service: MessageServiceAPI, -): MessageThreadMessagesServiceAPI { - return new ThreadMessagesService(platformServices, user, channel, files, applications, service); -} diff --git a/twake/backend/node/src/services/messages/services/messages/operations.ts b/twake/backend/node/src/services/messages/services/messages/operations.ts deleted file mode 100644 index 3419eb50ab..0000000000 --- a/twake/backend/node/src/services/messages/services/messages/operations.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { SaveResult, OperationType } from "../../../../core/platform/framework/api/crud-service"; -import { logger, TwakeContext } from "../../../../core/platform/framework"; -import { Message, TYPE as MessageTableName } from "../../entities/messages"; -import { - BookmarkOperation, - PinOperation, - ReactionOperation, - ThreadExecutionContext, -} from "../../types"; -import _ from "lodash"; -import { updateMessageReactions } from "./utils"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { MessageServiceAPI } from "../../api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { ThreadMessagesService } from "./service"; - -export class ThreadMessagesOperationsService { - constructor( - private database: DatabaseServiceAPI, - private service: MessageServiceAPI, - private threadMessagesService: ThreadMessagesService, - ) {} - repository: Repository; - - async init(context: TwakeContext): Promise { - this.repository = await this.database.getRepository(MessageTableName, Message); - return this; - } - - async pin( - operation: PinOperation, - options: {}, - context: ThreadExecutionContext, - ): Promise> { - if (!context?.user?.server_request && !this.service.threads.checkAccessToThread(context)) { - logger.error(`Unable to write in thread ${context.thread.id}`); - throw Error("Can't edit this message."); - } - - const message = await this.repository.findOne({ - thread_id: context.thread.id, - id: operation.id, - }); - - if (!message) { - logger.error(`This message doesn't exists`); - throw Error("Can't edit this message."); - } - - message.pinned_info = operation.pin - ? { - pinned_by: context.user.id, - pinned_at: new Date().getTime(), - } - : null; - - logger.info( - `Updated message ${operation.id} pin to ${JSON.stringify(message.pinned_info)} thread ${ - message.thread_id - }`, - ); - await this.repository.save(message); - this.threadMessagesService.onSaved(message, { created: false }, context); - return new SaveResult("message", message, OperationType.UPDATE); - } - - async reaction( - operation: ReactionOperation, - options: {}, - context: ThreadExecutionContext, - ): Promise> { - if (!context?.user?.server_request && !this.service.threads.checkAccessToThread(context)) { - logger.error(`Unable to write in thread ${context.thread.id}`); - throw Error("Can't edit this message."); - } - - const message = await this.repository.findOne({ - thread_id: context.thread.id, - id: operation.id, - }); - - if (!message) { - logger.error(`This message doesn't exists`); - throw Error("Can't edit this message."); - } - - //Update message reactions - updateMessageReactions(message, operation.reactions || [], context.user.id); - - logger.info( - `Updated message ${operation.id} reactions to ${JSON.stringify(message.reactions)} thread ${ - message.thread_id - }`, - ); - await this.repository.save(message); - this.threadMessagesService.onSaved(message, { created: false }, context); - return new SaveResult("message", message, OperationType.UPDATE); - } - - async bookmark( - operation: BookmarkOperation, - options: {}, - context: ThreadExecutionContext, - ): Promise> { - const message = await this.repository.findOne({ - thread_id: context.thread.id, - id: operation.id, - }); - - if (!message) { - logger.error(`This message doesn't exists`); - throw Error("Can't edit this message."); - } - - //TODO add message to user bookmarks - message.bookmarks = message.bookmarks.filter( - b => !(b.user_id === context.user.id && b.bookmark_id === operation.bookmark_id), - ); - if (operation.active) { - message.bookmarks.push({ - user_id: context.user.id, - bookmark_id: operation.bookmark_id, - created_at: new Date().getTime(), - }); - } - - logger.info( - `Added bookmark to message ${operation.id} => ${JSON.stringify( - message.bookmarks, - )} to thread ${message.thread_id}`, - ); - await this.repository.save(message); - this.threadMessagesService.onSaved(message, { created: false }, context); - - return new SaveResult("message", message, OperationType.UPDATE); - } -} diff --git a/twake/backend/node/src/services/messages/services/messages/service.ts b/twake/backend/node/src/services/messages/services/messages/service.ts deleted file mode 100644 index a71076edab..0000000000 --- a/twake/backend/node/src/services/messages/services/messages/service.ts +++ /dev/null @@ -1,644 +0,0 @@ -import { - SaveResult, - OperationType, - DeleteResult, - ListResult, - Pagination, - CrudExeption, -} from "../../../../core/platform/framework/api/crud-service"; -import { ResourcePath } from "../../../../core/platform/services/realtime/types"; -import { logger, RealtimeSaved, TwakeContext } from "../../../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { MessageServiceAPI, MessageThreadMessagesServiceAPI } from "../../api"; -import { - getInstance, - Message, - MessageWithUsers, - TYPE as MessageTableName, -} from "../../entities/messages"; -import { - getInstance as getMsgfileInstance, - MessageFile, - TYPE as MsgFileTableName, -} from "../../entities/message-files"; -import { - BookmarkOperation, - MessageLocalEvent, - MessagesGetThreadOptions, - MessagesSaveOptions, - MessageWithReplies, - MessageWithRepliesWithUsers, - PinOperation, - ReactionOperation, - ThreadExecutionContext, -} from "../../types"; -import { getThreadMessagePath, getThreadMessageWebsocketRoom } from "../../web/realtime"; -import { localEventBus } from "../../../../core/platform/framework/pubsub"; -import { buildMessageListPagination, getMentions } from "../utils"; -import _, { update } from "lodash"; -import { ThreadMessagesOperationsService } from "./operations"; -import { getDefaultMessageInstance } from "./utils"; -import { Thread } from "../../entities/threads"; -import UserServiceAPI from "../../../user/api"; -import ChannelServiceAPI from "../../../channels/provider"; -import { UserObject } from "../../../user/web/types"; -import { FileServiceAPI } from "../../../files/api"; -import { ApplicationServiceAPI } from "../../../applications/api"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export class ThreadMessagesService implements MessageThreadMessagesServiceAPI { - version: "1"; - repository: Repository; - msgFilesRepository: Repository; - operations: ThreadMessagesOperationsService; - - constructor( - private platformServices: PlatformServicesAPI, - private user: UserServiceAPI, - private channel: ChannelServiceAPI, - private files: FileServiceAPI, - private applications: ApplicationServiceAPI, - private service: MessageServiceAPI, - ) { - this.operations = new ThreadMessagesOperationsService(platformServices.database, service, this); - } - - async init(context: TwakeContext): Promise { - this.repository = await this.platformServices.database.getRepository( - MessageTableName, - Message, - ); - this.msgFilesRepository = await this.platformServices.database.getRepository( - MsgFileTableName, - MessageFile, - ); - await this.operations.init(context); - return this; - } - - /** - * Save a message - * The server / application / users can do different actions - * @param item - * @param options - * @param context - * @returns SaveResult - */ - async save( - item: Partial, - options?: MessagesSaveOptions, - context?: ThreadExecutionContext, - ): Promise> { - //This can come from: - // - Server want to change the message somehow (the message should already be formated) - // - Application change the message - // - User change its message - // - Pin / Reaction / Bookmark are *not* done here - - const serverRequest = context?.user?.server_request; - const applicationRequest = context?.user?.application_id; - let messageOwnerAndNotRemoved = true; - - item.thread_id = (serverRequest ? item.thread_id : null) || context.thread.id; - const pk = _.pick(item, "thread_id", "id"); - - let messageCreated = !pk.id; - - if (!pk.thread_id || (!serverRequest && !this.service.threads.checkAccessToThread(context))) { - logger.error(`Unable to write in thread ${context.thread.id}`); - throw Error("Can't write this message."); - } - - let message = getDefaultMessageInstance(item, context); - if (pk.id) { - const existingMessage = await this.repository.findOne(pk); - if (!existingMessage && !serverRequest) { - logger.error(`This message ${item.id} doesn't exists in thread ${item.thread_id}`); - throw Error("This message doesn't exists."); - } - if (existingMessage) { - message = existingMessage; - messageOwnerAndNotRemoved = - ((context.user?.id && message.user_id === context.user?.id) || - (context.user?.application_id && - message.application_id === context.user?.application_id)) && - message.subtype !== "deleted"; - - if (message.user_id === context.user?.id && context.user?.id) { - message.edited = { - edited_at: new Date().getTime(), - }; - } - } else { - messageCreated = true; - } - } - - const updatable: { [K in keyof Partial]: boolean } = { - ephemeral: serverRequest || messageOwnerAndNotRemoved, - subtype: serverRequest, - text: serverRequest || messageOwnerAndNotRemoved, - blocks: serverRequest || messageOwnerAndNotRemoved, - context: serverRequest || messageOwnerAndNotRemoved, - override: serverRequest || (messageOwnerAndNotRemoved && !!applicationRequest), - }; - Object.keys(updatable).forEach(k => { - if ((updatable as any)[k] && (item as any)[k] !== undefined) { - (message as any)[k] = (item as any)[k]; - } - }); - message = _.assign(message, pk); - - if (context.workspace && context.channel) { - message.cache = { - company_id: context.company.id, - workspace_id: context.workspace.id, - channel_id: context.channel.id, - }; - } - - if (!message.ephemeral) { - if (options.threadInitialMessage) { - message.id = message.thread_id; - } - - logger.info(`Saved message in thread ${message.thread_id}`); - await this.repository.save(message); - } else { - logger.info(`Did not save ephemeral message in thread ${message.thread_id}`); - } - - if (serverRequest || messageOwnerAndNotRemoved) { - message = await this.completeMessage(message, { files: item.files || [] }); - } - - await this.onSaved(message, { created: messageCreated }, context); - - return new SaveResult( - "message", - message, - messageCreated ? OperationType.CREATE : OperationType.UPDATE, - ); - } - - /** - * Move a message from a thread to another - * @param item - * @param options - * @param context - * @returns - */ - async move( - pk: Pick, - options: { previous_thread: string }, - context: ThreadExecutionContext, - ): Promise { - logger.debug( - `Try to move message ${pk.id} from thread ${options.previous_thread} to thread ${context.thread.id}`, - ); - - if (options.previous_thread === context.thread.id) { - return; - } - - //Move replies if it was a thread head message - if (pk.id === options.previous_thread) { - let nextPage: Pagination = { limitStr: "100" }; - do { - const replies = await this.list( - nextPage, - {}, - { - user: { id: null, server_request: true }, - thread: { id: pk.id }, - company: { id: context.company.id }, - }, - ); - - for (const reply of replies.getEntities()) { - //Do not create an infinite loop - if (reply.id !== options.previous_thread) { - logger.debug( - `Try to move reply ${reply.id} to message ${pk.id} from thread ${reply.thread_id} to thread ${context.thread.id}`, - ); - - await this.service.messages.move( - { id: reply.id || undefined }, - { - previous_thread: reply.thread_id, - }, - context, - ); - } - } - - nextPage = replies.nextPage as Pagination; - } while (nextPage.page_token); - } - - const messageInOldThread = await this.repository.findOne({ - thread_id: options.previous_thread, - id: pk.id, - }); - - if (!messageInOldThread) { - logger.error(`Unable to find message ${pk.id} in old thread ${context.thread.id}`); - throw Error("Can't move this message."); - } - - //Check new thread exists - let thread = await this.service.threads.get({ id: context.thread.id }); - if (!thread && `${context.thread.id}` === `${pk.id}`) { - logger.info("Create empty thread for message moved out of thread"); - const oldThread = await this.service.threads.get({ id: options.previous_thread }); - const upgradedContext = _.cloneDeep(context); - upgradedContext.user.server_request = true; - thread = ( - await this.service.threads.save( - { - id: messageInOldThread.id, - participants: oldThread.participants, - }, - {}, - upgradedContext, - ) - )?.entity; - } - if (!thread) { - throw Error("Can't move this message to inexistent thread."); - } - - const messageInNewThread = _.cloneDeep(messageInOldThread); - messageInNewThread.thread_id = context.thread.id; - - await this.repository.save(messageInNewThread); - - await this.onSaved(messageInNewThread, { created: true }, context); - - await this.repository.remove(messageInOldThread); - await this.service.threads.addReply(messageInOldThread.thread_id, -1); - - logger.info( - `Moved message ${pk.id} from thread ${options.previous_thread} to thread ${context.thread.id}`, - ); - - return; - } - - async forceDelete(pk: Message, context?: ThreadExecutionContext): Promise> { - return this.delete(pk, context, true); - } - - async delete( - pk: Message, - context?: ThreadExecutionContext, - forceDelete: boolean = false, - ): Promise> { - if (!context?.user?.server_request && !this.service.threads.checkAccessToThread(context)) { - logger.error(`Unable to write in thread ${context.thread.id}`); - throw Error("Can't edit this message."); - } - - const message = await this.repository.findOne({ - thread_id: context.thread.id, - id: pk.id, - }); - - if (!message) { - logger.error( - "This message does not exists, only remove it on websockets (ephemeral message)", - ); - - const msg = getInstance({ - subtype: "deleted", - ...pk, - }); - - msg.ephemeral = pk.ephemeral || { - id: pk.id, - version: "", - recipient: "", - recipient_context_id: "", - }; - - await this.onSaved(msg, { created: false }, context); - - return new DeleteResult("message", msg, true); - } - - if ( - !context?.user?.server_request && - message.user_id !== context.user.id && - message.application_id !== context?.user?.application_id - ) { - logger.error("You have no right to delete this message"); - throw Error("Can't delete this message."); - } - - message.subtype = "deleted"; - message.blocks = []; - message.reactions = []; - message.text = "Deleted message"; - message.files = []; - - logger.info(`Deleted message ${pk.id} from thread ${message.thread_id}`); - await this.repository.save(message); - await this.onSaved(message, { created: false }, context); - - //Only server and application can definively remove a message - if ( - (forceDelete && (context.user.server_request || context.user.application_id)) || - message.application_id - ) { - await this.repository.remove(message); - } - - return new DeleteResult("message", message, true); - } - - async getSingleMessage(pk: Pick) { - let message = await this.repository.findOne(pk); - if (message) { - message = await this.completeMessage(message, { files: message.files || [] }); - } - return message; - } - - async get( - pk: Pick, - context?: ThreadExecutionContext, - ): Promise { - const thread = await this.service.threads.get({ id: pk.id }, context); - if (thread) { - return await this.getThread(thread); - } else { - return await this.getSingleMessage(pk); - } - } - - async getThread( - thread: Thread, - options: MessagesGetThreadOptions = {}, - ): Promise { - const lastRepliesUncompleted = ( - await this.repository.find( - { - thread_id: thread.id, - }, - { - pagination: new Pagination("", `${options?.replies_per_thread || 3}`, false), - }, - ) - ).getEntities(); - - const lastReplies: Message[] = []; - for (const lastReply of lastRepliesUncompleted) { - if (lastReply) - lastReplies.push(await this.completeMessage(lastReply, { files: lastReply.files || [] })); - } - - const firstMessage = await this.getSingleMessage({ - thread_id: thread.id, - id: thread.id, - }); - - return { - ...firstMessage, - stats: { - replies: lastReplies.length === 1 ? 1 : thread.answers, //This line ensure the thread can be deleted by user if there is no replies - last_activity: thread.last_activity, - }, - last_replies: lastReplies.sort((a, b) => a.created_at - b.created_at), - }; - } - - async list( - pagination: Pagination, - options?: ListOption, - context?: ThreadExecutionContext, - ): Promise> { - const list = await this.repository.find( - { thread_id: context.thread.id }, - buildMessageListPagination(pagination, "id"), - ); - - //Get complete details about initial message - if ( - list - .getEntities() - .map(m => `${m.id}`) - .includes(`${context.thread.id}`) - ) { - const initialMessage = await this.get( - { thread_id: context.thread.id, id: context.thread.id }, - context, - ); - list.mapEntities((m: any) => { - if (`${m.id}` === `${initialMessage.id}`) { - return initialMessage; - } - return m; - }); - } - - return list; - } - - async includeUsersInMessage(message: Message): Promise { - let ids: string[] = []; - if (message.user_id) ids.push(message.user_id); - if (message.pinned_info?.pinned_by) ids.push(message.pinned_info?.pinned_by); - const mentions = getMentions(message); - for (const mentionedUser of mentions.users) { - ids.push(mentionedUser); - } - ids = _.uniq(ids); - - const users: UserObject[] = []; - for (const id of ids) { - users.push( - await this.user.formatUser( - await this.user.users.get({ id }, { user: { id: null, server_request: true } }), - ), - ); - } - - let application = null; - if (message.application_id) { - application = await this.applications.applications.get({ id: message.application_id }); - } - - const messageWithUsers = { ...message, users, application }; - return messageWithUsers; - } - - async includeUsersInMessageWithReplies( - message: MessageWithReplies, - ): Promise { - const last_replies = []; - for (const reply of message.last_replies) { - last_replies.push(await this.includeUsersInMessage(reply)); - } - - const messageWithUsers = { - ...message, - users: (await this.includeUsersInMessage(message)).users, - last_replies, - }; - return messageWithUsers; - } - - @RealtimeSaved((message, context) => [ - { - room: ResourcePath.get(getThreadMessageWebsocketRoom(context as ThreadExecutionContext)), - path: getThreadMessagePath(context as ThreadExecutionContext) + "/" + message.id, - }, - ]) - async onSaved(message: Message, options: { created?: boolean }, context: ThreadExecutionContext) { - if (options.created && !message.ephemeral) { - await this.service.threads.addReply(message.thread_id); - } - - //Depreciated way of doing this was localEventBus.publish("message:saved") - await this.service.engine.dispatchMessage({ - resource: message, - context: context, - created: options.created, - }); - - return new SaveResult( - "message", - message, - options.created ? OperationType.CREATE : OperationType.UPDATE, - ); - } - - async pin( - operation: PinOperation, - options: Record, - context: ThreadExecutionContext, - ): Promise> { - return this.operations.pin(operation, options, context); - } - - async reaction( - operation: ReactionOperation, - options: Record, - context: ThreadExecutionContext, - ): Promise> { - return this.operations.reaction(operation, options, context); - } - - async bookmark( - operation: BookmarkOperation, - options: Record, - context: ThreadExecutionContext, - ): Promise> { - return this.operations.bookmark(operation, options, context); - } - - //Complete message with all missing information and cache - async completeMessage(message: Message, options: { files?: Message["files"] } = {}) { - this.fixReactionsFormat(message); - if (options.files) message = await this.completeMessageFiles(message, options.files || []); - - //Mobile retro compatibility - if ((message.blocks?.length || 0) === 0) { - message.blocks = message.blocks || []; - message.blocks.push({ - type: "twacode", - elements: [message.text], - }); - } - - return message; - } - - //Fix https://github.com/linagora/Twake/issues/1559 - async fixReactionsFormat(message: Message) { - if (message.reactions?.length > 0) { - let foundError = false; - message.reactions.map(r => { - if (!(r.users?.length > 0)) { - foundError = true; - r.users = Object.values(r.users); - } - }); - if (foundError) await this.repository.save(message); - } - } - - async completeMessageFiles(message: Message, files: Message["files"]) { - if (files.length === 0 && (message.files || []).length === 0) { - return message; - } - - files = files.map(f => { - f.message_id = message.id; - return f; - }); - - const sameFile = (a: MessageFile["metadata"], b: MessageFile["metadata"]) => { - return _.isEqual(a.external_id, b.external_id) && a.source === b.source; - }; - - //Delete all existing msg files not in the new files object - const existingMsgFiles = ( - await this.msgFilesRepository.find({ - message_id: message.id, - }) - ).getEntities(); - for (const entity of existingMsgFiles) { - if (!files.some(f => sameFile(f.metadata, entity.metadata))) { - await this.msgFilesRepository.remove(entity); - } - } - - //Ensure all files in the file object are in the message - message.files = []; - for (const file of files) { - const entity = - existingMsgFiles.filter(e => sameFile(e.metadata, file.metadata))[0] || new MessageFile(); - entity.message_id = message.id; - entity.id = file.id || undefined; - entity.company_id = file.company_id; - - //For internal files, we have a special additional sync - if (file.metadata?.source == "internal") { - //Test external id format - if ( - message.files.length === 0 && - (typeof file.metadata.external_id === "string" || - !file.metadata.external_id?.company_id || - !file.metadata.external_id?.id) - ) { - console.log("File external_id format is wrong for source internal"); - continue; - } - - const original = await this.files.get(file.metadata.external_id?.id as string, { - user: { id: "", server_request: true }, - company: { id: file.metadata.external_id?.company_id as string }, - }); - if (original) { - file.metadata = { ...file.metadata, ...original.metadata }; - file.metadata.thumbnails = (file.metadata.thumbnails || []).map((t, index) => { - t.url = this.files.getThumbnailRoute(original, (t.index || index).toString()); - return t; - }); - } - } - - entity.metadata = file.metadata; - - await this.msgFilesRepository.save(entity); - - message.files.push(entity); - } - - await this.repository.save(message); - - return message; - } -} diff --git a/twake/backend/node/src/services/messages/services/messages/utils.ts b/twake/backend/node/src/services/messages/services/messages/utils.ts deleted file mode 100644 index 93fb15b108..0000000000 --- a/twake/backend/node/src/services/messages/services/messages/utils.ts +++ /dev/null @@ -1,97 +0,0 @@ -import _ from "lodash"; -import { getInstance, Message, MessageReaction } from "../../entities/messages"; -import { ThreadExecutionContext } from "../../types"; - -export function getSubtype( - item: Pick, - context?: ThreadExecutionContext, -): null | "application" | "deleted" | "system" { - //Application request - if (context?.user?.application_id) { - return item.subtype === "application" ? "application" : null; - } - //System request - else if (context?.user?.server_request) { - return item.subtype; - } - - //User cannot set a subtype itself - return null; -} - -export function updateMessageReactions( - message: Message, - selectedReactions: string[], - userId: string, -) { - let reactions: { [key: string]: MessageReaction } = {}; - for (const reaction of message.reactions || []) { - reactions[reaction.name] = reaction; - } - for (const reaction of selectedReactions) { - reactions[reaction] = reactions[reaction] || { name: reaction, count: 0, users: [] }; - } - for (const key in reactions) { - if (reactions[key].users.includes(userId)) { - reactions[key].count--; - reactions[key].users = reactions[key].users.filter(u => u != userId); - } - if (selectedReactions.includes(key)) { - reactions[key].count++; - reactions[key].users.push(userId); - } - if (reactions[key].count === 0) { - delete reactions[key]; - } - } - - message.reactions = Object.values(reactions); -} - -export function getDefaultMessageInstance(item: Partial, context: ThreadExecutionContext) { - let instance = getInstance({ - id: undefined, - ephemeral: - (context?.user?.application_id || context?.user?.server_request) && item.ephemeral - ? item.ephemeral - : null, - thread_id: (context?.user?.server_request ? item.thread_id : null) || context.thread.id, - type: context?.user?.server_request && item.type === "event" ? "event" : "message", - subtype: getSubtype({ subtype: item?.subtype || null }, context), - created_at: (context?.user?.server_request ? item.created_at : null) || new Date().getTime(), - user_id: (context?.user?.server_request ? item.user_id : null) || context.user.id, - application_id: - (context?.user?.server_request ? item.application_id : null) || - context?.user?.application_id || - null, - text: item.text || "", - blocks: item.blocks || [], - files: item.files || null, - context: item.context || null, - edited: (context?.user?.server_request ? item.edited : null) || null, //Message cannot be created with edition status - pinned_info: item.pinned_info - ? { - pinned_at: new Date().getTime(), - pinned_by: context.user.id, - } - : null, - reactions: (context?.user?.server_request ? item.reactions : null) || null, // Reactions cannot be set on creation - bookmarks: (context?.user?.server_request ? item.bookmarks : null) || null, - override: - (context?.user?.application_id || context?.user?.server_request) && item.override - ? { - title: item.override.title, - picture: item.override.picture, - } - : null, // Only apps and server can set an override on a message - }); - - if (context.user.server_request) { - instance = _.assign( - instance, - _.pickBy(item, v => v !== undefined), - ); - } - - return instance; -} diff --git a/twake/backend/node/src/services/messages/services/threads.ts b/twake/backend/node/src/services/messages/services/threads.ts new file mode 100644 index 0000000000..a5b204fdc1 --- /dev/null +++ b/twake/backend/node/src/services/messages/services/threads.ts @@ -0,0 +1,308 @@ +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Paginable, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { + Initializable, + logger, + TwakeContext, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { ParticipantObject, Thread } from "../entities/threads"; +import { CompanyExecutionContext, ThreadExecutionContext } from "../types"; +import { Message } from "../entities/messages"; +import _ from "lodash"; +import { extendExecutionContentWithChannel } from "../web/controllers"; +import gr from "../../global-resolver"; + +export class ThreadsService implements TwakeServiceProvider, Initializable { + version: "1"; + name: "ThreadsService"; + repository: Repository; + + async init(context: TwakeContext): Promise { + this.repository = await gr.database.getRepository("threads", Thread); + return this; + } + + /** + * Create a thread with its first message in it + * @param item + * @param options + * @param context + * @returns + */ + async save( + item: Pick & { + participants: Pick[]; + }, + options: { participants?: ParticipantOperation; message?: Message } = {}, + context?: CompanyExecutionContext, + ): Promise> { + if (item.id) { + //Update + const participantsOperation: ParticipantOperation = options.participants || { + add: [], + remove: [], + }; + + const thread = await this.repository.findOne({ id: item.id }, {}, context); + + if (thread) { + // Add the created_by information + participantsOperation.add = (participantsOperation.add || []).map(p => { + return { + created_by: context.user.id, + created_at: new Date().getTime(), + ...p, + }; + }) as ParticipantObject[]; + + thread.participants = _.uniqBy( + _.differenceBy( + [...thread.participants, ...participantsOperation.add], + participantsOperation.remove || [], + p => p.id, + ), + p => p.id, + ) as ParticipantObject[]; + + await this.repository.save(thread, context); + + //TODO ensure the thread is in all participants views (and removed from deleted participants) + + return new SaveResult( + "thread", + await this.getWithMessage({ id: thread.id }), + OperationType.UPDATE, + ); + } else { + //Thread to edit does not exists + + if (!context.user?.server_request) { + throw new Error("ThreadService: Unable to edit inexistent thread"); + } + } + } + + //Creation of thread or server edition + if (!options.message) { + if (context.user?.server_request) { + logger.info(`${this.name} - Create empty thread by server itself`); + } else { + throw new Error("You must provide an initial message in the thread."); + } + } + + //Enforce current user in the participants list and add the created_by information + const participants: ParticipantObject[] = [ + context.user.application_id ? {} : { type: "user", id: context.user.id }, + ...item.participants, + ].map(p => { + return { + created_by: context.user.id, + created_at: new Date().getTime(), + ...p, + }; + }) as ParticipantObject[]; + + const message: Message | null = options.message || null; + + const thread = new Thread(); + thread.created_at = new Date().getTime(); + thread.last_activity = thread.created_at; + thread.answers = 0; + thread.created_by = context.user.id; + thread.participants = _.uniqBy(participants, p => p.id); + + //If server request, we allow more + if (context.user?.server_request) { + thread.id = item.id; + thread.created_at = (item as Thread)?.created_at || thread.created_at; + } + + if (message && message.ephemeral) { + //We should not save if this is an ephemeral message + } else { + await this.repository.save(thread, context); + } + + if (message) { + message.status = "sent"; + + const result = await gr.services.messages.messages.save( + message, + { + threadInitialMessage: true, + }, + extendExecutionContentWithChannel( + participants, + Object.assign(context, { thread: { id: thread.id, company_id: context.company.id } }), + ), + ); + try { + const channelMembersCount = await gr.services.channels.members.getUsersCount({ + id: result.entity.cache.channel_id, + company_id: result.entity.cache.company_id, + workspace_id: result.entity.cache.workspace_id, + counter_type: "members", + }); + + if (channelMembersCount === 1) { + await gr.services.messages.messages.updateDeliveryStatus( + { + message_id: result.entity.id, + self_message: true, + status: "read", + thread_id: result.entity.thread_id, + }, + { + ...context, + thread: { id: thread.id }, + }, + ); + + await gr.services.channels.members.setChannelMemberReadSections( + { + start: result.entity.id, + end: result.entity.id, + }, + { + ...context, + channel_id: result.entity.cache.channel_id, + workspace_id: result.entity.cache.workspace_id, + }, + ); + } + } catch (err) { + logger.error("failed to update message delivery status"); + } + } + + return new SaveResult( + "thread", + await this.getWithMessage({ id: thread.id }), + OperationType.CREATE, + ); + } + + /** + * Add reply to thread: increase last_activity time and number of answers + * @param threadId + * @param increment + * @param context + */ + async addReply(threadId: string, increment: number = 1, context: ExecutionContext) { + const thread = await this.repository.findOne({ id: threadId }, {}, context); + if (thread) { + thread.answers = Math.max(0, (thread.answers || 0) + increment); + if (increment > 0) { + thread.last_activity = new Date().getTime(); + } + await this.repository.save(thread, context); + } else { + throw new Error("Try to add reply count to inexistent thread"); + } + } + + /** + * Add reply to thread: increase last_activity time and number of answers + * @param threadId + */ + async setReplyCount(threadId: string, count: number, context: ExecutionContext) { + const thread = await this.repository.findOne({ id: threadId }, {}, context); + if (thread) { + thread.answers = count; + await this.repository.save(thread, context); + } else { + throw new Error("Try to add reply count to inexistent thread"); + } + } + + /** + * Check context is allowed to accesss a thread + * @param context + * @returns + */ + async checkAccessToThread(context: ThreadExecutionContext): Promise { + if (context?.user?.server_request) { + return true; + } + + logger.info( + `Check access to thread ${context.thread.id} in company ${context.company.id} for user ${context.user.id} and app ${context?.user?.application_id}`, + ); + + const thread = await this.repository.findOne( + { + id: context.thread.id, + }, + {}, + context, + ); + + if (!thread) { + logger.info("No such thread"); + return false; + } + + //User is participant of the thread directly + if (thread.participants.some(p => p.type === "user" && p.id === context.user.id)) { + return true; + } + + //Check user is in one of the participant channels + for (const channel of thread.participants.filter(p => p.type === "channel")) { + if (true) { + //TODO get the channel_member from channel micro_service + return true; + } + } + + return false; + } + + get(pk: Pick, context: ExecutionContext): Promise { + return this.repository.findOne(pk, {}, context); + } + + async getWithMessage( + pk: Pick, + context?: ExecutionContext, + ): Promise { + const thread = await this.get(pk, context); + return { + ...thread, + message: await gr.services.messages.messages.get( + { id: pk.id, thread_id: pk.id }, + context as ThreadExecutionContext, + ), + }; + } + + async delete(pk: Pick, context?: ExecutionContext): Promise> { + const thread = await this.repository.findOne({ id: pk.id }, {}, context); + if (context.user.server_request) { + await this.repository.remove(thread, context); + } + return new DeleteResult("thread", thread, context.user.server_request && !!thread); + } + + list( + pagination: Paginable, + options?: ListOptions, + context?: ExecutionContext, + ): Promise> { + throw new Error("CRUD method not used."); + } +} + +type ParticipantOperation = { + add: Pick[]; + remove: Pick[]; +}; diff --git a/twake/backend/node/src/services/messages/services/threads/index.ts b/twake/backend/node/src/services/messages/services/threads/index.ts deleted file mode 100644 index 4b5cbfa3ca..0000000000 --- a/twake/backend/node/src/services/messages/services/threads/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { MessageServiceAPI, MessageThreadsServiceAPI } from "../../api"; -import { ThreadsService } from "./service"; - -export function getService( - databaseService: DatabaseServiceAPI, - service: MessageServiceAPI, -): MessageThreadsServiceAPI { - return new ThreadsService(databaseService, service); -} diff --git a/twake/backend/node/src/services/messages/services/threads/service.ts b/twake/backend/node/src/services/messages/services/threads/service.ts deleted file mode 100644 index e642c3a9a4..0000000000 --- a/twake/backend/node/src/services/messages/services/threads/service.ts +++ /dev/null @@ -1,257 +0,0 @@ -import { - CRUDService, - DeleteResult, - ExecutionContext, - ListResult, - OperationType, - Paginable, - SaveResult, -} from "../../../../core/platform/framework/api/crud-service"; -import { logger, TwakeContext } from "../../../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { MessageServiceAPI, MessageThreadsServiceAPI } from "../../api"; -import { ParticipantObject, Thread, ThreadPrimaryKey } from "../../entities/threads"; -import { CompanyExecutionContext, ThreadExecutionContext } from "../../types"; -import { Message } from "../../entities/messages"; -import _ from "lodash"; -import { extendExecutionContentWithChannel } from "../../web/controllers"; - -export class ThreadsService - implements MessageThreadsServiceAPI, CRUDService -{ - version: "1"; - name: "ThreadsService"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI, private service: MessageServiceAPI) {} - - async init(context: TwakeContext): Promise { - this.repository = await this.database.getRepository("threads", Thread); - return this; - } - - /** - * Create a thread with its first message in it - * @param item - * @param options - * @param context - * @returns - */ - async save( - item: Pick & { - participants: Pick[]; - }, - options: { participants?: ParticipantOperation; message?: Message } = {}, - context?: CompanyExecutionContext, - ): Promise> { - if (item.id) { - //Update - const participantsOperation: ParticipantOperation = options.participants || { - add: [], - remove: [], - }; - - const thread = await this.repository.findOne({ id: item.id }); - - if (thread) { - // Add the created_by information - participantsOperation.add = (participantsOperation.add || []).map(p => { - return { - created_by: context.user.id, - created_at: new Date().getTime(), - ...p, - }; - }) as ParticipantObject[]; - - thread.participants = _.uniqBy( - _.differenceBy( - [...thread.participants, ...participantsOperation.add], - participantsOperation.remove || [], - p => p.id, - ), - p => p.id, - ) as ParticipantObject[]; - - await this.repository.save(thread); - - //TODO ensure the thread is in all participants views (and removed from deleted participants) - - return new SaveResult( - "thread", - await this.getWithMessage({ id: thread.id }), - OperationType.UPDATE, - ); - } else { - //Thread to edit does not exists - - if (!context.user?.server_request) { - throw new Error("ThreadService: Unable to edit inexistent thread"); - } - } - } - - //Creation of thread or server edition - if (!options.message) { - if (context.user?.server_request) { - logger.info(`${this.name} - Create empty thread by server itself`); - } else { - throw new Error("You must provide an initial message in the thread."); - } - } - - //Enforce current user in the participants list and add the created_by information - const participants: ParticipantObject[] = [ - { type: "user", id: context.user.id }, - ...item.participants, - ].map(p => { - return { - created_by: context.user.id, - created_at: new Date().getTime(), - ...p, - }; - }) as ParticipantObject[]; - - const message: Message | null = options.message || null; - - const thread = new Thread(); - thread.created_at = new Date().getTime(); - thread.last_activity = thread.created_at; - thread.answers = 0; - thread.created_by = context.user.id; - thread.participants = _.uniqBy(participants, p => p.id); - - //If server request, we allow more - if (context.user?.server_request) { - thread.id = item.id; - thread.created_at = (item as Thread)?.created_at || thread.created_at; - } - - await this.repository.save(thread); - - if (message) { - await this.service.messages.save( - message, - { - threadInitialMessage: true, - }, - extendExecutionContentWithChannel( - participants, - Object.assign(context, { thread: { id: thread.id, company_id: context.company.id } }), - ), - ); - } - - return new SaveResult( - "thread", - await this.getWithMessage({ id: thread.id }), - OperationType.CREATE, - ); - } - - /** - * Add reply to thread: increase last_activity time and number of answers - * @param threadId - */ - async addReply(threadId: string, increment: number = 1) { - const thread = await this.repository.findOne({ id: threadId }); - if (thread) { - thread.answers = Math.max(0, (thread.answers || 0) + increment); - if (increment > 0) { - thread.last_activity = new Date().getTime(); - } - await this.repository.save(thread); - } else { - throw new Error("Try to add reply count to inexistent thread"); - } - } - - /** - * Add reply to thread: increase last_activity time and number of answers - * @param threadId - */ - async setReplyCount(threadId: string, count: number) { - const thread = await this.repository.findOne({ id: threadId }); - if (thread) { - thread.answers = count; - await this.repository.save(thread); - } else { - throw new Error("Try to add reply count to inexistent thread"); - } - } - - /** - * Check context is allowed to accesss a thread - * @param context - * @returns - */ - async checkAccessToThread(context: ThreadExecutionContext): Promise { - if (context?.user?.server_request) { - return true; - } - - logger.info( - `Check access to thread ${context.thread.id} in company ${context.company.id} for user ${context.user.id} and app ${context?.user?.application_id}`, - ); - - const thread = await this.repository.findOne({ - id: context.thread.id, - }); - - if (!thread) { - logger.info("No such thread"); - return false; - } - - //User is participant of the thread directly - if (thread.participants.some(p => p.type === "user" && p.id === context.user.id)) { - return true; - } - - //Check user is in one of the participant channels - for (const channel of thread.participants.filter(p => p.type === "channel")) { - if (true) { - //TODO get the channel_member from channel micro_service - return true; - } - } - - return false; - } - - get(pk: Pick, context?: ExecutionContext): Promise { - return this.repository.findOne(pk); - } - - async getWithMessage( - pk: Pick, - context?: ExecutionContext, - ): Promise { - const thread = await this.get(pk); - return { - ...thread, - message: await this.service.messages.get({ id: pk.id, thread_id: pk.id }, context), - }; - } - - async delete(pk: Pick, context?: ExecutionContext): Promise> { - const thread = await this.repository.findOne({ id: pk.id }); - if (context.user.server_request) { - await this.repository.remove(thread); - } - return new DeleteResult("thread", thread, context.user.server_request && !!thread); - } - - list( - pagination: Paginable, - options?: ListOptions, - context?: ExecutionContext, - ): Promise> { - throw new Error("CRUD method not used."); - } -} - -type ParticipantOperation = { - add: Pick[]; - remove: Pick[]; -}; diff --git a/twake/backend/node/src/services/messages/services/user-bookmarks.ts b/twake/backend/node/src/services/messages/services/user-bookmarks.ts new file mode 100644 index 0000000000..a727e8829b --- /dev/null +++ b/twake/backend/node/src/services/messages/services/user-bookmarks.ts @@ -0,0 +1,111 @@ +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Pagination, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { + Initializable, + RealtimeDeleted, + RealtimeSaved, + TwakeContext, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { getInstance, UserMessageBookmark } from "../entities/user-message-bookmarks"; +import { CompanyExecutionContext } from "../types"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import { getUserBookmarksWebsocketRoom } from "../web/realtime"; +import gr from "../../global-resolver"; + +export class UserBookmarksService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(context: TwakeContext): Promise { + this.repository = await gr.database.getRepository( + "user_message_bookmarks", + UserMessageBookmark, + ); + return this; + } + + get( + pk: Pick, + context: CompanyExecutionContext, + ): Promise { + return this.repository.findOne(pk, {}, context); + } + + @RealtimeSaved((bookmark, context) => [ + { + room: ResourcePath.get(getUserBookmarksWebsocketRoom(context as CompanyExecutionContext)), + path: getUserBookmarksWebsocketRoom(context as CompanyExecutionContext) + "/" + bookmark.id, + }, + ]) + async save( + { company_id, user_id, id, name }: SaveParams, + context: CompanyExecutionContext, + ): Promise> { + //Disallow duplicates + const entities = (await this.list({ user_id, company_id }, context)).getEntities(); + + for (const entity of entities) { + if (name === entity.name) { + return new SaveResult( + "user_message_bookmark", + entity, + OperationType.EXISTS, + ); + } + } + + const instance = getInstance({ + company_id: company_id, + user_id: user_id, + name, + }); + if (id) { + instance.id = id; + } + await this.repository.save(instance, context); + + return new SaveResult( + "user_message_bookmark", + instance, + id ? OperationType.UPDATE : OperationType.CREATE, + ); + } + + @RealtimeDeleted((bookmark, context) => [ + { + room: ResourcePath.get(getUserBookmarksWebsocketRoom(context as CompanyExecutionContext)), + path: getUserBookmarksWebsocketRoom(context as CompanyExecutionContext) + "/" + bookmark.id, + }, + ]) + async delete( + pk: Pick, + context?: CompanyExecutionContext, + ): Promise> { + const instance = await this.repository.findOne(pk, {}, context); + if (instance) await this.repository.remove(instance, context); + return new DeleteResult("user_message_bookmark", instance, !!instance); + } + + async list( + { user_id, company_id, pagination }: ListParams, + context: ExecutionContext, + ): Promise> { + return this.repository.find({ user_id, company_id }, { pagination }, context); + } +} + +type SaveParams = { user_id: string; company_id: string; name: string; id: string; test?: string }; + +type ListParams = { + company_id: string; + user_id: string; + pagination?: Pagination; +}; diff --git a/twake/backend/node/src/services/messages/services/user-bookmarks/index.ts b/twake/backend/node/src/services/messages/services/user-bookmarks/index.ts deleted file mode 100644 index 150bb65f50..0000000000 --- a/twake/backend/node/src/services/messages/services/user-bookmarks/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { MessageUserBookmarksServiceAPI } from "../../api"; -import { UserBookmarksService } from "./service"; - -export function getService(databaseService: DatabaseServiceAPI): MessageUserBookmarksServiceAPI { - return new UserBookmarksService(databaseService); -} diff --git a/twake/backend/node/src/services/messages/services/user-bookmarks/service.ts b/twake/backend/node/src/services/messages/services/user-bookmarks/service.ts deleted file mode 100644 index faf7c90430..0000000000 --- a/twake/backend/node/src/services/messages/services/user-bookmarks/service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { - SaveResult, - DeleteResult, - ListResult, - OperationType, - Pagination, -} from "../../../../core/platform/framework/api/crud-service"; -import { RealtimeDeleted, RealtimeSaved, TwakeContext } from "../../../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { MessageUserBookmarksServiceAPI } from "../../api"; -import { getInstance, UserMessageBookmark } from "../../entities/user-message-bookmarks"; -import { CompanyExecutionContext } from "../../types"; -import { ResourcePath } from "../../../../core/platform/services/realtime/types"; -import { getUserBookmarksWebsocketRoom } from "../../web/realtime"; - -export class UserBookmarksService implements MessageUserBookmarksServiceAPI { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI) {} - - async init(context: TwakeContext): Promise { - this.repository = await this.database.getRepository( - "user_message_bookmarks", - UserMessageBookmark, - ); - return this; - } - - get( - pk: Pick, - context?: CompanyExecutionContext, - ): Promise { - return this.repository.findOne(pk); - } - - @RealtimeSaved((bookmark, context) => [ - { - room: ResourcePath.get(getUserBookmarksWebsocketRoom(context as CompanyExecutionContext)), - path: getUserBookmarksWebsocketRoom(context as CompanyExecutionContext) + "/" + bookmark.id, - }, - ]) - async save( - item: Pick, - options?: SaveOptions, - context?: CompanyExecutionContext, - ): Promise> { - //Disallow duplicates - const entities = (await this.list(null, {}, context)).getEntities(); - for (const entity of entities) { - if (item.name === entity.name) { - return new SaveResult( - "user_message_bookmark", - entity, - OperationType.EXISTS, - ); - } - } - - const instance = getInstance({ - company_id: context.company.id, - user_id: context.user.id, - ...item, - }); - await this.repository.save(instance); - return new SaveResult( - "user_message_bookmark", - instance, - item.id ? OperationType.UPDATE : OperationType.CREATE, - ); - } - - @RealtimeDeleted((bookmark, context) => [ - { - room: ResourcePath.get(getUserBookmarksWebsocketRoom(context as CompanyExecutionContext)), - path: getUserBookmarksWebsocketRoom(context as CompanyExecutionContext) + "/" + bookmark.id, - }, - ]) - async delete( - pk: Pick, - context?: CompanyExecutionContext, - ): Promise> { - const instance = await this.repository.findOne(pk); - if (instance) await this.repository.remove(instance); - return new DeleteResult("user_message_bookmark", instance, !!instance); - } - - async list( - pagination: Pagination, - options?: ListOption, - context?: CompanyExecutionContext, - ): Promise> { - const list = await this.repository.find( - { user_id: context.user.id, company_id: context.company.id }, - { pagination }, - ); - return list; - } -} diff --git a/twake/backend/node/src/services/messages/services/utils.ts b/twake/backend/node/src/services/messages/services/utils.ts index a3620bdfb0..fae3ea4860 100644 --- a/twake/backend/node/src/services/messages/services/utils.ts +++ b/twake/backend/node/src/services/messages/services/utils.ts @@ -1,7 +1,18 @@ import { FindOptions } from "../../../core/platform/services/database/services/orm/repository/repository"; -import { Pagination } from "../../../core/platform/framework/api/crud-service"; +import { + CreateResult, + Pagination, + UpdateResult, +} from "../../../core/platform/framework/api/crud-service"; import { Message } from "../entities/messages"; -import { specialMention } from "../types"; +import { MessageLocalEvent, SpecialMention, ThreadExecutionContext } from "../types"; +import User from "../../../services/user/entities/user"; +import { RealtimeEntityActionType } from "../../../core/platform/services/realtime/types"; +import { getThreadMessagePath } from "../web/realtime"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import { RealtimeLocalBusEvent } from "../../../core/platform/services/realtime/types"; +import { localEventBus } from "../../../core/platform/framework/event-bus"; +import { ParticipantObject } from "../entities/threads"; export const buildMessageListPagination = ( pagination: Pagination, @@ -16,14 +27,78 @@ export const buildMessageListPagination = ( }; }; -export const getMentions = (messageResource: Message) => { +export const getMentions = async ( + messageResource: Message, + findByUsername: (username: string) => Promise, +) => { + const idsFromUsernames = []; + try { + const usersNoIdOutput = (messageResource.text || "").match(/( |^)@[a-zA-Z0-9-_.]+/gm); + const usernames = (usersNoIdOutput || []).map(u => (u || "").trim().split("@").pop()); + for (const username of usernames) { + if (!"all|here|channel|everyone".split("|").includes(username)) { + const user = await findByUsername(username); + if (user) idsFromUsernames.push(user.id); + } + } + } catch (err) { + console.log(err); + } + const usersOutput = (messageResource.text || "").match(/@[^: ]+:([0-f-]{36})/gm); const globalOutput = (messageResource.text || "").match( /(^| )@(all|here|channel|everyone)([^a-z]|$)/gm, ); return { - users: (usersOutput || []).map(u => (u || "").trim().split(":").pop()), - specials: (globalOutput || []).map(g => (g || "").trim().split("@").pop()) as specialMention[], + users: [ + ...(usersOutput || []).map(u => (u || "").trim().split(":").pop()), + ...idsFromUsernames, + ], + specials: (globalOutput || []).map(g => (g || "").trim().split("@").pop()) as SpecialMention[], }; }; + +/** + * extracts the links from a message + * + * @param {Message} messageResource - The message to be parsed + * @returns {String} - links found in the message + */ +export const getLinks = (messageResource: Message): string[] => { + const cleanText = messageResource.text.replace(/\n+/gm, " "); + const links = (cleanText || "").match(/https?:\/\/[^ ]+/gm); + + return links || []; +}; + +/** + * Publish a message to the realtime bus + * + * @param {MessageLocalEvent} message - The event to be published + * @param {ParticipantObject} participant - The participant + */ +export const publishMessageInRealtime = ( + message: MessageLocalEvent, + participant: ParticipantObject, +): void => { + if (participant.type !== "channel") return; + + const room = `/companies/${participant.company_id}/workspaces/${participant.workspace_id}/channels/${participant.id}/feed`; + const type = "message"; + const entity = message.resource; + const context = message.context; + + localEventBus.publish("realtime:publish", { + topic: message.created ? RealtimeEntityActionType.Created : RealtimeEntityActionType.Updated, + event: { + type, + room: ResourcePath.get(room), + resourcePath: getThreadMessagePath(context as ThreadExecutionContext) + "/" + entity.id, + entity, + result: message.created + ? new CreateResult(type, entity) + : new UpdateResult(type, entity), + }, + } as RealtimeLocalBusEvent); +}; diff --git a/twake/backend/node/src/services/messages/services/views.ts b/twake/backend/node/src/services/messages/services/views.ts new file mode 100644 index 0000000000..55be1416bb --- /dev/null +++ b/twake/backend/node/src/services/messages/services/views.ts @@ -0,0 +1,460 @@ +import _, { uniqBy } from "lodash"; +import { + Initializable, + TwakeContext, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import { + ExecutionContext, + ListResult, + Paginable, + Pagination, +} from "../../../core/platform/framework/api/crud-service"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import SearchRepository from "../../../core/platform/services/search/repository"; +import { fileIsMedia } from "../../../services/files/utils"; +import { formatUser } from "../../../utils/users"; +import gr from "../../global-resolver"; +import { MessageChannelMarkedRef } from "../entities/message-channel-marked-refs"; +import { MessageChannelRef } from "../entities/message-channel-refs"; +import { MessageFileRef } from "../entities/message-file-refs"; +import { MessageFile } from "../entities/message-files"; +import { Message } from "../entities/messages"; +import { Thread } from "../entities/threads"; +import { + ChannelViewExecutionContext, + CompanyExecutionContext, + FlatFileFromMessage, + FlatPinnedFromMessage, + MessageViewListOptions, + MessageWithReplies, + SearchMessageFilesOptions, + SearchMessageOptions, +} from "../types"; +import { FileSearchResult } from "../web/controllers/views/search-files"; +import { buildMessageListPagination } from "./utils"; + +export class ViewsServiceImpl implements TwakeServiceProvider, Initializable { + version: "1"; + repositoryChannelRefs: Repository; + repositoryThreads: Repository; + repositoryFilesRef: Repository; + repositoryMessageFile: Repository; + repositoryMarkedRef: Repository; + searchRepository: SearchRepository; + searchFilesRepository: SearchRepository; + + async init(context: TwakeContext): Promise { + this.searchRepository = gr.platformServices.search.getRepository("messages", Message); + this.searchFilesRepository = gr.platformServices.search.getRepository( + "message_files", + MessageFile, + ); + this.repositoryThreads = await gr.database.getRepository("threads", Thread); + this.repositoryChannelRefs = await gr.database.getRepository( + "message_channel_refs", + MessageChannelRef, + ); + this.repositoryFilesRef = await gr.database.getRepository( + "message_file_refs", + MessageFileRef, + ); + this.repositoryMarkedRef = await gr.database.getRepository( + "message_channel_marked_refs", + MessageChannelMarkedRef, + ); + this.repositoryMessageFile = await gr.database.getRepository( + "message_files", + MessageFile, + ); + + return this; + } + + async listChannelFiles( + pagination: Pagination, + options?: MessageViewListOptions, + context?: ChannelViewExecutionContext, + ): Promise> { + const refs = await this.repositoryFilesRef.find( + { + target_type: options?.media_only + ? "channel_media" + : options?.file_only + ? "channel_file" + : "channel", + target_id: context.channel.id, + company_id: context.channel.company_id, + }, + buildMessageListPagination(pagination, "id"), + ); + + const threads: (MessageWithReplies & { context: MessageFileRef })[] = []; + for (const ref of refs.getEntities()) { + const thread = await this.repositoryThreads.findOne({ id: ref.thread_id }, {}); + const extendedThread = await gr.services.messages.messages.getThread( + thread, + { + replies_per_thread: options.replies_per_thread || 1, + }, + context, + ); + + const message = await gr.services.messages.messages.get({ + thread_id: ref.thread_id, + id: ref.message_id, + }); + if (message && extendedThread) { + extendedThread.highlighted_replies = [message]; + threads.push({ ...extendedThread, context: ref }); + } + } + + if (options.flat) { + let files: FlatFileFromMessage[] = []; + for (const thread of threads) { + for (const reply of thread.highlighted_replies) { + for (const file of reply.files || []) { + if (file.id === thread.context.message_file_id) { + files.push({ + file: file as MessageFile, + thread, + context: thread.context, + }); + } + } + } + } + files = _.uniqBy(files, f => f.file.id); + refs.nextPage.page_token = files.length > 0 ? files[files.length - 1].context?.id : null; + return new ListResult("file", files, refs.nextPage); + } + + return new ListResult("thread", threads, refs.nextPage); + } + + async listChannelPinned( + pagination: Pagination, + options?: MessageViewListOptions, + context?: ChannelViewExecutionContext, + ): Promise> { + const refs = await this.repositoryMarkedRef.find( + { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + type: "pinned", + channel_id: context.channel.id, + }, + buildMessageListPagination(pagination, "thread_id"), + context, + ); + + const threads: MessageWithReplies[] = []; + for (const ref of uniqBy(refs.getEntities(), "thread_id")) { + const thread = await this.repositoryThreads.findOne({ id: ref.thread_id }, {}); + const extendedThread = await gr.services.messages.messages.getThread( + thread, + { + replies_per_thread: options.replies_per_thread || 1, + }, + context, + ); + if (extendedThread) { + threads.push(extendedThread); + } + } + + for (const ref of refs.getEntities()) { + const extendedThread = threads.find(th => th.id === ref.thread_id); + if (extendedThread) { + extendedThread.highlighted_replies = extendedThread.highlighted_replies || []; + const message = await gr.services.messages.messages.get({ + thread_id: ref.thread_id, + id: ref.message_id, + }); + extendedThread.highlighted_replies.push(message); + } + } + + if (options.flat) { + const messages: FlatPinnedFromMessage[] = []; + for (const thread of threads) { + for (const message of thread.highlighted_replies) { + messages.push({ + message, + thread, + }); + } + } + return new ListResult("message", messages, refs.nextPage); + } + + return new ListResult("thread", threads, null); + } + + async listChannelThreads( + pagination: Pagination, + options?: MessageViewListOptions, + context?: ChannelViewExecutionContext, + ): Promise> { + return this.listChannel(pagination, { ...options, replies_per_thread: 0 }, context); + } + + /** + * Get last threads in a channel. + * + * We can do great improvements in the number of calls we currently do: + - Get last threads refs (1req) + - For each ref get the corresponding thread (to get number of replies => can be cached in the thread ref itself) (threads x reqs) + - For each thread, get first message (=> first message id can be cached in thread ref too and so replace this request by a $in) (threads x reqs) + - For each thread get last N replies (threads x reqs) + + Total requests for "get last 20 threads with their last 3 replies": + + 1 + + 20 (can be cached in first req) + + 20 (can be replaced by a $in ) + + 20 + ---- + = 61 reqs + * @param pagination + * @param options + * @param context + * @returns + */ + async listChannel( + pagination: Paginable, + options?: MessageViewListOptions, + context?: ChannelViewExecutionContext, + ): Promise> { + const threadsRefs = await this.repositoryChannelRefs.find( + { + company_id: context.channel.company_id, + workspace_id: context.channel.workspace_id, + channel_id: context.channel.id, + }, + buildMessageListPagination(Pagination.fromPaginable(pagination), "message_id"), + context, + ); + + const threads = uniqBy( + ( + await this.repositoryThreads.find( + {}, + { + $in: [["id", threadsRefs.getEntities().map(ref => ref.thread_id)]], + }, + context, + ) + ).getEntities(), + thread => thread.id, + ); + + //Get first message for each thread and add last replies for each thread + let threadWithLastMessages: MessageWithReplies[] = []; + if (options.replies_per_thread !== 0) { + await Promise.all( + threads.map(async (thread: Thread) => { + const extendedThread = await gr.services.messages.messages.getThread( + thread, + { + replies_per_thread: options.replies_per_thread || 3, + }, + context, + ); + + if ( + extendedThread?.last_replies?.length === 0 && + extendedThread.created_at > new Date().getTime() - 1000 * 60 //This is important to avoid removing thread if people loads a channel at the same time people create a thread + ) { + await gr.services.messages.threads.delete( + { id: extendedThread.thread_id }, + { user: { id: null, server_request: true } }, + ); + } else if (extendedThread) { + threadWithLastMessages.push(extendedThread); + } + }), + ); + } + threadWithLastMessages = threadWithLastMessages + .filter(m => m.id) + .sort((a, b) => a.stats.last_activity - b.stats.last_activity); + + return new ListResult("thread", threadWithLastMessages, threadsRefs.nextPage); + } + + async search( + pagination: Pagination, + options: SearchMessageOptions, + context?: ExecutionContext, + ): Promise> { + return await this.searchRepository + .search( + { + ...(options.hasFiles ? { has_files: true } : {}), + ...(options.hasMedias ? { has_medias: true } : {}), + }, + { + pagination, + ...(options.companyId ? { $in: [["company_id", [options.companyId]]] } : {}), + ...(options.workspaceId ? { $in: [["workspace_id", [options.workspaceId]]] } : {}), + ...(options.channelId ? { $in: [["channel_id", [options.channelId]]] } : {}), + ...(options.sender ? { $in: [["user_id", [options.sender]]] } : {}), + $text: { + $search: options.search, + }, + $sort: { + created_at: "desc", + }, + }, + context, + ) + .then(a => { + return a; + }); + } + + async searchFiles( + pagination: Pagination, + options: SearchMessageFilesOptions, + context?: ExecutionContext, + ): Promise> { + const temp = await this.searchFilesRepository.search( + { + ...(options.isFile ? { is_file: true } : {}), + ...(options.isMedia ? { is_media: true } : {}), + }, + { + pagination, + ...(options.companyId ? { $in: [["cache_company_id", [options.companyId]]] } : {}), + ...(options.workspaceId ? { $in: [["cache_workspace_id", [options.workspaceId]]] } : {}), + ...(options.channelId ? { $in: [["cache_channel_id", [options.channelId]]] } : {}), + ...(options.sender ? { $in: [["cache_user_id", [options.sender]]] } : {}), + ...(options.extension ? { $in: [["extension", [options.extension]]] } : {}), + $text: { + $search: options.search, + }, + $sort: { + created_at: "desc", + }, + }, + context, + ); + + return new ListResult(temp.type, await this.checkFiles(temp.getEntities()), temp.nextPage); + } + + async listUserMarkedFiles( + userId: string, + type: "user_upload" | "user_download" | "both", + media: "file_only" | "media_only" | "both", + context: CompanyExecutionContext, + pagination: Pagination, + ): Promise> { + let files: (MessageFile & { context: MessageFileRef })[] = []; + let nextPageUploads: Paginable; + let nextPageDownloads: Paginable; + do { + const uploads = + type === "user_upload" || type === "both" + ? await this.repositoryFilesRef + .find( + { target_type: "user_upload", target_id: userId, company_id: context.company.id }, + { + pagination: { ...pagination, page_token: nextPageUploads?.page_token }, + }, + context, + ) + .then(a => { + nextPageUploads = a.nextPage; + return a.getEntities(); + }) + : []; + + const downloads = + type === "user_download" || type === "both" + ? await this.repositoryFilesRef + .find( + { target_type: "user_download", target_id: userId, company_id: context.company.id }, + { + pagination: { ...pagination, page_token: nextPageDownloads?.page_token }, + }, + context, + ) + .then(a => { + nextPageDownloads = a.nextPage; + return a.getEntities(); + }) + : []; + + const refs = [...uploads, ...downloads]; + + const messageFilePromises: Promise[] = refs.map( + async ref => { + try { + const res = { + ...(await this.repositoryMessageFile.findOne( + { + message_id: ref.message_id, + id: ref.message_file_id, + }, + {}, + context, + )), + context: ref, + }; + + return res; + } catch (e) { + return null; + } + }, + ); + + const messageFiles = _.uniqBy( + (await Promise.all(messageFilePromises)).filter(a => a), + a => a.metadata?.source + JSON.stringify(a.metadata?.external_id), + ); + + files = [...files, ...messageFiles.filter(a => a)].filter(ref => { + //Apply media filer + const isMedia = fileIsMedia(ref); + return !((media === "file_only" && isMedia) || (media === "media_only" && !isMedia)); + }); + files = files.sort((a, b) => b.created_at - a.created_at); + } while ( + files.length < (parseInt(pagination.limitStr) || 100) && + (nextPageDownloads?.page_token || nextPageUploads?.page_token) + ); + + const fileWithUserAndMessagePromise: Promise[] = files.map( + async file => + ({ + user: await formatUser(await gr.services.users.getCached({ id: file.cache?.user_id })), + message: await gr.services.messages.messages.get({ + id: file.message_id, + thread_id: file.thread_id, + }), + ...file, + } as FileSearchResult), + ); + const fileWithUserAndMessage = await Promise.all(fileWithUserAndMessagePromise); + + return new ListResult( + "file", + await this.checkFiles(fileWithUserAndMessage), + nextPageUploads || nextPageDownloads, + ); + } + + async checkFiles(files: T[]): Promise { + const results = await Promise.all( + files.map(async file => { + if (file.metadata.source !== "internal") return true; + const ei = file.metadata.external_id; + return await gr.services.files.exists(ei.id, ei.company_id); + }), + ); + return files.filter((_v, index) => results[index]); + } +} diff --git a/twake/backend/node/src/services/messages/services/views/index.ts b/twake/backend/node/src/services/messages/services/views/index.ts deleted file mode 100644 index dfd2a44e2d..0000000000 --- a/twake/backend/node/src/services/messages/services/views/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { MessageServiceAPI, MessageViewsServiceAPI } from "../../api"; -import { ViewsService } from "./service"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - service: MessageServiceAPI, -): MessageViewsServiceAPI { - return new ViewsService(platformServices, service); -} diff --git a/twake/backend/node/src/services/messages/services/views/service.ts b/twake/backend/node/src/services/messages/services/views/service.ts deleted file mode 100644 index 40945a0580..0000000000 --- a/twake/backend/node/src/services/messages/services/views/service.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { - ExecutionContext, - ListResult, - Pagination, -} from "../../../../core/platform/framework/api/crud-service"; -import { TwakeContext } from "../../../../core/platform/framework"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { MessageServiceAPI, MessageViewsServiceAPI } from "../../api"; -import { Message } from "../../entities/messages"; -import { Thread } from "../../entities/threads"; -import { - ChannelViewExecutionContext, - MessageViewListOptions, - MessageWithReplies, -} from "../../types"; -import { MessageChannelRef } from "../../entities/message-channel-refs"; -import { buildMessageListPagination } from "../utils"; -import { uniqBy, isEqual, uniqWith } from "lodash"; -import { SearchUserOptions } from "../../../user/services/users/types"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; -import SearchRepository from "../../../../core/platform/services/search/repository"; -import { uuid } from "../../../../utils/types"; -import { MessageFileRef } from "../../entities/message-file-refs"; -import { MessageChannelMarkedRef } from "../../entities/message-channel-marked-refs"; - -export class ViewsService implements MessageViewsServiceAPI { - version: "1"; - repositoryChannelRefs: Repository; - repository: Repository; - repositoryThreads: Repository; - repositoryFilesRef: Repository; - repositoryMarkedRef: Repository; - searchRepository: SearchRepository; - - constructor(private platformServices: PlatformServicesAPI, private service: MessageServiceAPI) {} - - async init(context: TwakeContext): Promise { - this.searchRepository = this.platformServices.search.getRepository( - "messages", - Message, - ); - this.repository = await this.platformServices.database.getRepository( - "messages", - Message, - ); - this.repositoryThreads = await this.platformServices.database.getRepository( - "threads", - Thread, - ); - this.repositoryChannelRefs = - await this.platformServices.database.getRepository( - "message_channel_refs", - MessageChannelRef, - ); - this.repositoryFilesRef = await this.platformServices.database.getRepository( - "message_file_refs", - MessageFileRef, - ); - this.repositoryMarkedRef = - await this.platformServices.database.getRepository( - "message_channel_marked_refs", - MessageChannelMarkedRef, - ); - - return this; - } - - async listChannelFiles( - pagination: Pagination, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise> { - const refs = await this.repositoryFilesRef.find( - { target_type: "channel", target_id: context.channel.id }, - buildMessageListPagination(pagination, "id"), - ); - - let threads: MessageWithReplies[] = []; - for (const ref of refs.getEntities()) { - const thread = await this.repositoryThreads.findOne({ id: ref.thread_id }); - const extendedThread = await this.service.messages.getThread(thread, { - replies_per_thread: options.replies_per_thread || 1, - }); - - const message = await this.repository.findOne({ - thread_id: ref.thread_id, - id: ref.message_id, - }); - if (message && extendedThread) { - extendedThread.highlighted_replies = [message]; - threads.push(extendedThread); - } - } - - return new ListResult("thread", threads, refs.nextPage); - } - - async listChannelPinned( - pagination: Pagination, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise> { - const refs = await this.repositoryMarkedRef.find( - { - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - type: "pinned", - channel_id: context.channel.id, - }, - buildMessageListPagination(pagination, "thread_id"), - ); - - let threads: MessageWithReplies[] = []; - for (const ref of refs.getEntities()) { - const thread = await this.repositoryThreads.findOne({ id: ref.thread_id }); - const extendedThread = await this.service.messages.getThread(thread, { - replies_per_thread: options.replies_per_thread || 1, - }); - - if (extendedThread) { - threads.push(extendedThread); - } - } - - return new ListResult("thread", [], null); - } - - async listChannelThreads( - pagination: Pagination, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise> { - return this.listChannel(pagination, { ...options, replies_per_thread: 0 }, context); - } - - /** - * Get last threads in a channel. - * - * We can do great improvements in the number of calls we currently do: - - Get last threads refs (1req) - - For each ref get the corresponding thread (to get number of replies => can be cached in the thread ref itself) (threads x reqs) - - For each thread, get first message (=> first message id can be cached in thread ref too and so replace this request by a $in) (threads x reqs) - - For each thread get last N replies (threads x reqs) - - Total requests for "get last 20 threads with their last 3 replies": - + 1 - + 20 (can be cached in first req) - + 20 (can be replaced by a $in ) - + 20 - ---- - = 61 reqs - * @param pagination - * @param options - * @param context - * @returns - */ - async listChannel( - pagination: Pagination, - options?: MessageViewListOptions, - context?: ChannelViewExecutionContext, - ): Promise> { - const threadsRefs = await this.repositoryChannelRefs.find( - { - company_id: context.channel.company_id, - workspace_id: context.channel.workspace_id, - channel_id: context.channel.id, - }, - buildMessageListPagination(pagination, "message_id"), - ); - - const threads = uniqBy( - ( - await this.repositoryThreads.find( - {}, - { - $in: [["id", threadsRefs.getEntities().map(ref => ref.thread_id)]], - }, - ) - ).getEntities(), - thread => thread.id, - ); - - //Get first message for each thread and add last replies for each thread - let threadWithLastMessages: MessageWithReplies[] = []; - if (options.replies_per_thread !== 0) { - await Promise.all( - threads.map(async (thread: Thread) => { - const extendedThread = await this.service.messages.getThread(thread, { - replies_per_thread: options.replies_per_thread || 3, - }); - - if ( - extendedThread?.last_replies?.length === 0 && - extendedThread.created_at > new Date().getTime() - 1000 * 60 //This is important to avoid removing thread if people loads a channel at the same time people create a thread - ) { - await this.service.threads.delete( - { id: extendedThread.thread_id }, - { user: { id: null, server_request: true } }, - ); - } else if (extendedThread) { - threadWithLastMessages.push(extendedThread); - } - }), - ); - } - threadWithLastMessages = threadWithLastMessages - .filter(m => m.id) - .sort((a, b) => a.stats.last_activity - b.stats.last_activity); - - return new ListResult("thread", threadWithLastMessages, threadsRefs.nextPage); - } - - async search( - pagination: Pagination, - options?: SearchUserOptions, - context?: ExecutionContext, - ): Promise> { - return await this.searchRepository.search( - {}, - { - pagination, - ...(options.companyId ? { $in: [["company_id", [options.companyId]]] } : {}), - ...(options.workspaceId ? { $in: [["workspace_id", [options.workspaceId]]] } : {}), - $text: { - $search: options.search, - }, - }, - ); - } - - async getThreadsFirstMessages(threadsIds: uuid[]): Promise { - threadsIds = uniqWith(threadsIds, isEqual); - const items = threadsIds.map(threadId => - this.repository - .find({ thread_id: threadId }, { pagination: new Pagination("", "1", true) }) - .then(a => a.getEntities()[0]), - ); - return Promise.all(items); - } -} diff --git a/twake/backend/node/src/services/messages/types.ts b/twake/backend/node/src/services/messages/types.ts index 3e036c55c1..c65498eafc 100644 --- a/twake/backend/node/src/services/messages/types.ts +++ b/twake/backend/node/src/services/messages/types.ts @@ -1,11 +1,14 @@ import { ExecutionContext } from "../../core/platform/framework/api/crud-service"; import { uuid } from "../../utils/types"; +import { HookType } from "../applications-api/types"; +import { Channel } from "../channels/entities"; import { UserObject } from "../user/web/types"; -import { MessageFileMetadata } from "./entities/message-files"; +import { MessageFileRef } from "./entities/message-file-refs"; +import { MessageFile } from "./entities/message-files"; import { Message, MessageWithUsers } from "./entities/messages"; import { Thread } from "./entities/threads"; -export type specialMention = "all" | "here" | "everyone" | "channel"; +export type SpecialMention = "all" | "here" | "everyone" | "channel"; export type MessageNotification = { company_id: uuid; @@ -18,7 +21,7 @@ export type MessageNotification = { mentions?: { users?: uuid[]; teams?: uuid[]; - specials?: specialMention[]; + specials?: SpecialMention[]; }; sender_name?: string; @@ -30,8 +33,15 @@ export type MessageNotification = { text: string; }; +export type MessageHook = HookType & { + channel: Channel; + thread: Thread; + message: Message; +}; + export type MessageWithReplies = Message & { last_replies: Message[]; + thread?: MessageWithReplies; highlighted_replies?: Message[]; stats: { last_activity: number; @@ -41,6 +51,8 @@ export type MessageWithReplies = Message & { export type MessageWithRepliesWithUsers = MessageWithReplies & { last_replies: MessageWithUsers[]; + thread?: MessageWithRepliesWithUsers; + highlighted_replies?: MessageWithUsers[]; users: UserObject[]; }; @@ -74,9 +86,12 @@ export interface PaginationQueryParameters { direction?: "history" | "future"; } export interface MessageViewListOptions { - include_users: boolean; - replies_per_thread: number; - emojis: boolean; + include_users?: boolean; + replies_per_thread?: number; + flat?: boolean; + emojis?: boolean; + media_only?: boolean; + file_only?: boolean; } export interface MessageListQueryParameters extends PaginationQueryParameters { @@ -99,6 +114,11 @@ export interface BookmarkOperation { active: boolean; } +export type MessageFileDownloadEvent = { + user: { id: string }; + operation: { message_id: string; thread_id: string; message_file_id: string }; +}; + export interface MessagesSaveOptions { threadInitialMessage?: boolean; enforceViewPropagation?: boolean; @@ -107,4 +127,62 @@ export interface MessagesSaveOptions { } export interface MessagesGetThreadOptions { replies_per_thread?: number; + includeQuoteInMessage?: boolean; } + +export type SearchMessageOptions = { + search?: string; + companyId?: string; + workspaceId?: string; + channelId?: string; + hasFiles?: boolean; + hasMedias?: boolean; + sender?: string; +}; + +export type SearchMessageFilesOptions = { + search?: string; + companyId?: string; + workspaceId?: string; + channelId?: string; + sender?: string; + isFile?: boolean; + isMedia?: boolean; + extension?: string; +}; + +export type InboxOptions = { + companyId: string; +}; + +export type FlatFileFromMessage = { + file: MessageFile; + thread: MessageWithReplies; + context: MessageFileRef; +}; + +export type FlatPinnedFromMessage = { + message: any; + thread: any; +}; + +export interface DeleteLinkOperation { + message_id: string; + thread_id: string; + link: string; +} + +export type UpdateDeliveryStatusOperation = { + status: "delivered" | "read"; + self_message?: boolean; +} & MessageIdentifier; + +export type MessageReadType = { + messages: MessageIdentifier[]; + channel_id: string; +}; + +export type MessageIdentifier = { + message_id: string; + thread_id: string; +}; diff --git a/twake/backend/node/src/services/messages/utils.ts b/twake/backend/node/src/services/messages/utils.ts new file mode 100644 index 0000000000..414bf1e433 --- /dev/null +++ b/twake/backend/node/src/services/messages/utils.ts @@ -0,0 +1,32 @@ +import { MessageFile } from "./entities/message-files"; +import { Message } from "./entities/messages"; +import { MessageWithReplies } from "./types"; + +export const formatMessageFile = (file: MessageFile): MessageFile => { + return { + ...file, + metadata: { + ...file.metadata, + thumbnails: [ + ...file.metadata.thumbnails.map(thumbnail => ({ + ...thumbnail, + full_url: thumbnail.url.match(/https?:\/\//) + ? "/internal/services/files/v1/" + thumbnail.url.replace(/^\//, "") + : thumbnail.url, + })), + ], + }, + }; +}; + +export const formatMessage = ( + message: MessageWithReplies | Message, +): MessageWithReplies | Message => { + return { + ...message, + files: message.files.map(formatMessageFile), + ...((message as MessageWithReplies).last_replies + ? { last_replies: (message as MessageWithReplies).last_replies.map(formatMessage) } + : {}), + }; +}; diff --git a/twake/backend/node/src/services/messages/web/controllers/messages-files.ts b/twake/backend/node/src/services/messages/web/controllers/messages-files.ts new file mode 100644 index 0000000000..cccd4c4a29 --- /dev/null +++ b/twake/backend/node/src/services/messages/web/controllers/messages-files.ts @@ -0,0 +1,52 @@ +import gr from "../../../global-resolver"; +import { FastifyRequest, FastifyReply } from "fastify"; + +export class MessagesFilesController { + async deleteMessageFile( + request: FastifyRequest<{ + Params: { + company_id: string; + message_id: string; + message_file_id: string; + }; + }>, + reply: FastifyReply, + ) { + const user = request.currentUser; + const resp = await gr.services.messages.messagesFiles.deleteMessageFile( + request.params.message_id, + request.params.message_file_id, + user.id, + ); + + if (!resp) reply.code(404).send(); + + reply.send({ resource: resp }); + } + + async getMessageFile( + request: FastifyRequest<{ + Params: { + company_id: string; + message_id: string; + message_file_id: string; + }; + }>, + reply: FastifyReply, + ) { + const user = request.currentUser; + const resp = await gr.services.messages.messagesFiles.getMessageFile( + request.params.message_id, + request.params.message_file_id, + ); + + if (!resp) reply.code(404).send(); + + //Check user has access to this file (check access to channel) + if (!(await gr.services.channels.members.getChannelMember(user, resp.channel))) { + reply.code(403).send(); + } + + reply.send({ resource: resp }); + } +} diff --git a/twake/backend/node/src/services/messages/web/controllers/messages.ts b/twake/backend/node/src/services/messages/web/controllers/messages.ts index a17ef21195..b29b3a1075 100644 --- a/twake/backend/node/src/services/messages/web/controllers/messages.ts +++ b/twake/backend/node/src/services/messages/web/controllers/messages.ts @@ -1,20 +1,26 @@ import { FastifyReply, FastifyRequest } from "fastify"; import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { MessageServiceAPI } from "../../api"; import { ResourceDeleteResponse, ResourceGetResponse, ResourceListResponse, ResourceUpdateResponse, } from "../../../../utils/types"; -import { Message } from "../../entities/messages"; -import { MessageListQueryParameters, ThreadExecutionContext } from "../../types"; +import { getInstance as getMessageInstance, Message } from "../../entities/messages"; +import { + CompanyExecutionContext, + MessageListQueryParameters, + MessageReadType, + ThreadExecutionContext, +} from "../../types"; import { handleError } from "../../../../utils/handleError"; -import { Pagination } from "../../../../core/platform/framework/api/crud-service"; +import { CrudException, Pagination } from "../../../../core/platform/framework/api/crud-service"; import { getThreadMessageWebsocketRoom } from "../realtime"; import { ThreadPrimaryKey } from "../../entities/threads"; import { extendExecutionContentWithChannel } from "./index"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import gr from "../../../global-resolver"; +import { formatUser } from "../../../../utils/users"; +import { UserObject } from "../../../../services/user/web/types"; export class MessagesController implements @@ -25,8 +31,6 @@ export class MessagesController ResourceDeleteResponse > { - constructor(protected realtime: RealtimeServiceAPI, protected service: MessageServiceAPI) {} - async save( request: FastifyRequest<{ Querystring: { @@ -50,7 +54,7 @@ export class MessagesController try { if (request.body.options?.previous_thread) { //First move the message to another thread, then edit it - await this.service.messages.move( + await gr.services.messages.messages.move( { id: request.params.message_id || undefined }, { previous_thread: request.body.options?.previous_thread, @@ -59,13 +63,48 @@ export class MessagesController ); } - const thread = await this.service.threads.get({ id: context.thread.id } as ThreadPrimaryKey); + const thread = await gr.services.messages.threads.get( + { + id: context.thread.id, + } as ThreadPrimaryKey, + context, + ); if (!thread) { throw "Message must be in a thread"; } - const result = await this.service.messages.save( + let hasOneMembership = false; + for (const participant of thread.participants) { + if (thread.created_by === context.user.id) { + hasOneMembership = true; + break; + } + if (participant.type === "channel") { + const isMember = await gr.services.channels.members.getChannelMember( + { id: context.user.id }, + { + company_id: participant.company_id, + workspace_id: participant.workspace_id, + id: participant.id, + }, + ); + if (isMember) { + hasOneMembership = true; + break; + } + } else if (participant.type === "user") { + if (participant.id === context.user.id) { + hasOneMembership = true; + break; + } + } + } + if (!hasOneMembership) { + throw CrudException.notFound("You can't post in this thread"); + } + + const result = await gr.services.messages.messages.save( { id: request.params.message_id || undefined, ...request.body.resource, @@ -77,7 +116,7 @@ export class MessagesController let entity = result.entity; if (request.query.include_users) { - entity = await this.service.messages.includeUsersInMessage(entity); + entity = await gr.services.messages.messages.includeUsersInMessage(entity, context); } return { @@ -100,11 +139,11 @@ export class MessagesController ) { const context = getThreadExecutionContext(request); try { - await this.service.messages.forceDelete( - { + await gr.services.messages.messages.forceDelete( + getMessageInstance({ thread_id: request.params.thread_id, id: request.params.message_id, - }, + }), context, ); return { @@ -127,11 +166,11 @@ export class MessagesController ): Promise { const context = getThreadExecutionContext(request); try { - await this.service.messages.delete( - { + await gr.services.messages.messages.delete( + getMessageInstance({ thread_id: request.params.thread_id, id: request.params.message_id, - }, + }), context, ); return { @@ -155,7 +194,7 @@ export class MessagesController ): Promise> { const context = getThreadExecutionContext(request); try { - let resource = await this.service.messages.get( + let resource = await gr.services.messages.messages.get( { thread_id: request.params.thread_id, id: request.params.message_id, @@ -164,7 +203,7 @@ export class MessagesController ); if (request.query.include_users) { - resource = await this.service.messages.includeUsersInMessage(resource); + resource = await gr.services.messages.messages.includeUsersInMessage(resource, context); } return { @@ -187,7 +226,7 @@ export class MessagesController ): Promise> { const context = getThreadExecutionContext(request); try { - const resources = await this.service.messages.list( + const resources = await gr.services.messages.messages.list( new Pagination( request.query.page_token, request.query.limit, @@ -200,7 +239,7 @@ export class MessagesController let entities = []; if (request.query.include_users) { for (const msg of resources.getEntities()) { - entities.push(await this.service.messages.includeUsersInMessage(msg)); + entities.push(await gr.services.messages.messages.includeUsersInMessage(msg, context)); } } else { entities = resources.getEntities(); @@ -209,7 +248,7 @@ export class MessagesController return { resources: entities, ...(request.query.websockets && { - websockets: this.realtime.sign( + websockets: gr.platformServices.realtime.sign( [{ room: getThreadMessageWebsocketRoom(context) }], context.user.id, ), @@ -238,7 +277,7 @@ export class MessagesController ): Promise> { const context = getThreadExecutionContext(request); try { - const result = await this.service.messages.reaction( + const result = await gr.services.messages.messages.reaction( { id: request.params.message_id, reactions: request.body.reactions, @@ -270,7 +309,7 @@ export class MessagesController ): Promise> { const context = getThreadExecutionContext(request); try { - const result = await this.service.messages.bookmark( + const result = await gr.services.messages.messages.bookmark( { id: request.params.message_id, bookmark_id: request.body.bookmark_id, @@ -302,7 +341,7 @@ export class MessagesController ): Promise> { const context = getThreadExecutionContext(request); try { - const result = await this.service.messages.pin( + const result = await gr.services.messages.messages.pin( { id: request.params.message_id, pin: request.body.pin, @@ -317,6 +356,154 @@ export class MessagesController handleError(reply, err); } } + + async download( + request: FastifyRequest<{ + Params: { + company_id: string; + thread_id: string; + message_id: string; + message_file_id: string; + }; + }>, + reply: FastifyReply, + ): Promise<{ status: "ok" }> { + const context = getThreadExecutionContext(request); + try { + await gr.services.messages.messages.download( + { + id: request.params.message_id, + thread_id: request.params.thread_id, + message_file_id: request.params.message_file_id, + }, + {}, + context, + ); + return { + status: "ok", + }; + } catch (err) { + handleError(reply, err); + } + } + + /** + * Delete link preview handler + * + * @param {FastifyRequest} request - The request object + * @param {FastifyReply} reply - The reply object + * @returns {Promise>} - The response object + */ + async deleteLinkPreview( + request: FastifyRequest<{ + Params: { + company_id: string; + thread_id: string; + message_id: string; + encoded_url: string; + }; + Body: { + url: string; + }; + }>, + reply: FastifyReply, + ): Promise> { + const context = getThreadExecutionContext(request); + try { + const result = await gr.services.messages.messages.deleteLinkPreview( + { + message_id: request.params.message_id, + thread_id: request.params.thread_id, + link: request.body.url, + }, + context, + ); + + return { + resource: result.entity, + }; + } catch (err) { + handleError(reply, err); + } + } + + /** + * Mark messages as seen + * + * @param {FastifyRequest} request - The request object + * @param {FastifyReply} reply - The reply object + * @returns {Promise} - The response promise + */ + async read( + request: FastifyRequest<{ + Params: { + company_id: string; + workspace_id: string; + }; + Body: MessageReadType; + }>, + reply: FastifyReply, + ): Promise { + try { + const { messages, channel_id } = request.body; + const context: CompanyExecutionContext = { + company: { id: request.params.company_id }, + user: request.currentUser, + url: request.url, + method: request.routerMethod, + reqId: request.id, + transport: "http", + }; + + const result = await gr.services.messages.messages.read(messages, { + ...context, + channel_id, + workspace_id: request.params.workspace_id, + }); + return !!result; + } catch (err) { + handleError(reply, err); + return false; + } + } + + /** + * get users who've seen the message + * + * @param {FastifyRequest} request - the request object + * @param {FastifyReply} reply - the reply object + * @returns {Promise>} - the users list + */ + async seenBy( + request: FastifyRequest<{ + Params: { + company_id: string; + workspace_id: string; + thread_id: string; + message_id: string; + }; + }>, + reply: FastifyReply, + ): Promise> { + try { + const { message_id, workspace_id } = request.params; + const context = getThreadExecutionContext(request); + + const userIds = await gr.services.messages.messages.listSeenBy(message_id, { + ...context, + workspace: { id: workspace_id }, + }); + + const users = await Promise.all(userIds.map(id => gr.services.users.get({ id }, context))); + const resources = await Promise.all(users.map(user => formatUser(user))); + + return { + resources, + }; + } catch (error) { + handleError(reply, error); + } + } } function getThreadExecutionContext( diff --git a/twake/backend/node/src/services/messages/web/controllers/threads.ts b/twake/backend/node/src/services/messages/web/controllers/threads.ts index a2af60b0ac..495179b1d1 100644 --- a/twake/backend/node/src/services/messages/web/controllers/threads.ts +++ b/twake/backend/node/src/services/messages/web/controllers/threads.ts @@ -1,6 +1,5 @@ import { FastifyReply, FastifyRequest } from "fastify"; import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { MessageServiceAPI } from "../../api"; import { ResourceCreateResponse, ResourceDeleteResponse, @@ -10,6 +9,8 @@ import { import { handleError } from "../../../../utils/handleError"; import { CompanyExecutionContext } from "../../types"; import { ParticipantObject, Thread } from "../../entities/threads"; +import gr from "../../../global-resolver"; +import { CrudException } from "../../../../core/platform/framework/api/crud-service"; export class ThreadsController implements @@ -18,9 +19,8 @@ export class ThreadsController ResourceCreateResponse, ResourceListResponse, ResourceDeleteResponse - > { - constructor(protected service: MessageServiceAPI) {} - + > +{ async save( request: FastifyRequest<{ Params: { @@ -40,8 +40,29 @@ export class ThreadsController reply: FastifyReply, ): Promise> { const context = getCompanyExecutionContext(request); + + const participants = + (request.body.resource.participants?.length + ? request.body.resource?.participants + : request.body.options?.participants?.add) || []; + for (const participant of participants) { + if (participant.type === "channel") { + const isMember = await gr.services.channels.members.getChannelMember( + { id: context.user.id }, + { + company_id: participant.company_id, + workspace_id: participant.workspace_id, + id: participant.id, + }, + ); + if (!isMember) { + throw CrudException.notFound("Channel not found"); + } + } + } + try { - const result = await this.service.threads.save( + const result = await gr.services.messages.threads.save( { id: request.params.thread_id || undefined, participants: request.body.resource.participants || undefined, diff --git a/twake/backend/node/src/services/messages/web/controllers/user-bookmarks.ts b/twake/backend/node/src/services/messages/web/controllers/user-bookmarks.ts index e6d7aa1d08..0e075305e6 100644 --- a/twake/backend/node/src/services/messages/web/controllers/user-bookmarks.ts +++ b/twake/backend/node/src/services/messages/web/controllers/user-bookmarks.ts @@ -1,19 +1,16 @@ import { FastifyReply, FastifyRequest } from "fastify"; import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { MessageServiceAPI } from "../../api"; import { - ResourceUpdateResponse, ResourceDeleteResponse, ResourceGetResponse, ResourceListResponse, - ResourceWebsocket, + ResourceUpdateResponse, } from "../../../../utils/types"; -import { getInstance, UserMessageBookmark } from "../../entities/user-message-bookmarks"; -import { ExecutionContext, SaveResult } from "../../../../core/platform/framework/api/crud-service"; +import { UserMessageBookmark } from "../../entities/user-message-bookmarks"; import { handleError } from "../../../../utils/handleError"; import { CompanyExecutionContext } from "../../types"; import { getUserBookmarksWebsocketRoom } from "../realtime"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import gr from "../../../global-resolver"; export class UserBookmarksController implements @@ -24,8 +21,6 @@ export class UserBookmarksController ResourceDeleteResponse > { - constructor(protected realtime: RealtimeServiceAPI, protected service: MessageServiceAPI) {} - async save( request: FastifyRequest<{ Params: { @@ -42,14 +37,13 @@ export class UserBookmarksController ): Promise> { const context = getCompanyExecutionContext(request); try { - const result = await this.service.userBookmarks.save( + const result = await gr.services.messages.userBookmarks.save( { user_id: context.user.id, company_id: request.params.company_id, name: request.body.resource.name, id: request.params.id || undefined, }, - {}, context, ); return { @@ -71,7 +65,7 @@ export class UserBookmarksController ): Promise { const context = getCompanyExecutionContext(request); try { - const result = await this.service.userBookmarks.delete( + const result = await gr.services.messages.userBookmarks.delete( { user_id: context.user.id, company_id: request.params.company_id, @@ -97,16 +91,15 @@ export class UserBookmarksController ): Promise> { const context = getCompanyExecutionContext(request); try { - const list = await this.service.userBookmarks.list( - {}, + const list = await gr.services.messages.userBookmarks.list( { user_id: context.user.id, - company_id: request.params.company_id, + company_id: context.company.id, }, context, ); return { - websockets: this.realtime.sign( + websockets: gr.platformServices.realtime.sign( [{ room: getUserBookmarksWebsocketRoom(context) }], context.user.id, ), diff --git a/twake/backend/node/src/services/messages/web/controllers/views.ts b/twake/backend/node/src/services/messages/web/controllers/views.ts index b3ef64138b..4cd20aacac 100644 --- a/twake/backend/node/src/services/messages/web/controllers/views.ts +++ b/twake/backend/node/src/services/messages/web/controllers/views.ts @@ -1,36 +1,28 @@ import { FastifyReply, FastifyRequest } from "fastify"; -import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { MessageServiceAPI } from "../../api"; -import { - ResourceCreateResponse, - ResourceDeleteResponse, - ResourceGetResponse, - ResourceListResponse, -} from "../../../../utils/types"; +import { ResourceListResponse } from "../../../../utils/types"; import { Message } from "../../entities/messages"; import { handleError } from "../../../../utils/handleError"; -import { ListResult, Pagination } from "../../../../core/platform/framework/api/crud-service"; +import { + CrudException, + ListResult, + Pagination, +} from "../../../../core/platform/framework/api/crud-service"; import { ChannelViewExecutionContext, + FlatFileFromMessage, + FlatPinnedFromMessage, MessageViewListOptions, - PaginationQueryParameters, MessageWithReplies, + PaginationQueryParameters, } from "../../types"; -import { keyBy } from "lodash"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; - -export class ViewsController - implements - CrudController< - ResourceGetResponse, - ResourceCreateResponse, - ResourceListResponse, - ResourceDeleteResponse - > -{ - constructor(protected realtime: RealtimeServiceAPI, protected service: MessageServiceAPI) {} - - async list( +import gr from "../../../global-resolver"; +import { CompanyExecutionContext } from "../../../applications/web/types"; +import { PublicFile } from "../../../files/entities/file"; +import searchFiles from "./views/search-files"; +import recentFiles from "./views/recent-files"; + +export class ViewsController { + async feed( request: FastifyRequest<{ Querystring: MessageViewListQueryParameters; Params: { @@ -40,7 +32,9 @@ export class ViewsController }; }>, reply: FastifyReply, - ): Promise> { + ): Promise< + ResourceListResponse + > { const pagination = new Pagination( request.query.page_token, request.query.limit, @@ -49,17 +43,29 @@ export class ViewsController const query = { ...request.query, include_users: request.query.include_users }; const context = getChannelViewExecutionContext(request); - let resources: ListResult; + const isMember = await gr.services.channels.members.getChannelMember( + { id: context.user.id }, + { + company_id: request.params.company_id, + workspace_id: request.params.workspace_id, + id: request.params.channel_id, + }, + ); + if (!isMember) { + throw CrudException.notFound("Channel not found"); + } + + let resources: ListResult; try { if (request.query.filter === "files") { - resources = await this.service.views.listChannelFiles(pagination, query, context); + resources = await gr.services.messages.views.listChannelFiles(pagination, query, context); } else if (request.query.filter === "thread") { - resources = await this.service.views.listChannelThreads(pagination, query, context); + resources = await gr.services.messages.views.listChannelThreads(pagination, query, context); } else if (request.query.filter === "pinned") { - resources = await this.service.views.listChannelPinned(pagination, query, context); + resources = await gr.services.messages.views.listChannelPinned(pagination, query, context); } else { - resources = await this.service.views.listChannel(pagination, query, context); + resources = await gr.services.messages.views.listChannel(pagination, query, context); } if (!resources) { @@ -69,7 +75,34 @@ export class ViewsController let entities = []; if (request.query.include_users) { for (const msg of resources.getEntities()) { - entities.push(await this.service.messages.includeUsersInMessageWithReplies(msg)); + if (request.query.flat) { + entities.push({ + ...msg, + ...((msg as any).message + ? { + message: await gr.services.messages.messages.includeUsersInMessageWithReplies( + (msg as any).message, + context, + ), + } + : {}), + ...((msg as any).thread + ? { + thread: await gr.services.messages.messages.includeUsersInMessageWithReplies( + (msg as any).thread, + context, + ), + } + : {}), + } as FlatFileFromMessage | FlatPinnedFromMessage); + } else { + entities.push( + await gr.services.messages.messages.includeUsersInMessageWithReplies( + msg as MessageWithReplies, + context, + ), + ); + } } } else { entities = resources.getEntities(); @@ -78,7 +111,7 @@ export class ViewsController return { resources: entities, ...(request.query.websockets && { - websockets: this.realtime.sign( + websockets: gr.platformServices.realtime.sign( [ { room: `/companies/${context.channel.company_id}/workspaces/${context.channel.workspace_id}/channels/${context.channel.id}/feed`, @@ -96,41 +129,138 @@ export class ViewsController } } + // Bookmarked messages of user from all over workspace + async bookmarks(): Promise> { + return { resources: [] }; + } + + // Uploaded and downloaded files of user from all over workspace + files = recentFiles; + + // Latest messages of user from all over workspace + async inbox( + request: FastifyRequest<{ + Querystring: MessageViewListQueryParameters; + Params: { + company_id: string; + }; + }>, + reply: FastifyReply, + ): Promise> { + const context = getCompanyExecutionContext(request); + const messages = await gr.services.messages.messages.inbox( + request.currentUser.id, + context, + new Pagination(null, String(request.query.limit)), + ); + + return { + resources: messages.getEntities(), + }; + } + async search( request: FastifyRequest<{ - Querystring: MessageViewSearchQueryParameters; + Querystring: MessageViewSearchQueryParameters & { page_token: string }; Params: { company_id: string; }; }>, context: ChannelViewExecutionContext, - ): Promise> { - const messages: Message[] = await this.service.views - .search( - new Pagination(request.query.page_token, request.query.limit), + ): Promise> { + if (request.query.q.length < 1) { + return { resources: [] }; + } + + const limit = +request.query.limit || 100; + + async function* getNextMessages( + initialPageToken?: string, + ): AsyncIterableIterator<{ msg: Message; pageToken: string }> { + let lastPageToken = initialPageToken; + let messages: Message[] = []; + let hasMoreMessages = true; + do { + messages = await gr.services.messages.views + .search( + new Pagination(lastPageToken, limit.toString()), + { + search: request.query.q, + workspaceId: request.query.workspace_id, + channelId: request.query.channel_id, + companyId: request.params.company_id, + ...(request.query.has_files ? { hasFiles: true } : {}), + ...(request.query.has_medias ? { hasMedias: true } : {}), + ...(request.query.sender ? { sender: request.query.sender } : {}), + }, + context, + ) + .then((a: ListResult) => { + lastPageToken = a.nextPage.page_token; + if (!lastPageToken) { + hasMoreMessages = false; + } + return a.getEntities(); + }); + + if (messages.length) { + for (const message of messages) { + yield { msg: message, pageToken: lastPageToken }; + } + } else { + hasMoreMessages = false; + } + } while (hasMoreMessages); + } + + const messages = [] as Message[]; + let lastPageToken = null; + + for await (const { msg, pageToken } of getNextMessages(request.query.page_token)) { + lastPageToken = pageToken; + const getChannelMember = await gr.services.channels.members.getChannelMember( + { id: request.currentUser.id }, { - search: request.query.q, - companyId: request.params.company_id, + company_id: msg.cache.company_id, + workspace_id: msg.cache.workspace_id, + id: msg.cache.channel_id, }, + 50, context, - ) - .then(a => a.getEntities()); + ); + if (!getChannelMember) continue; - const firstMessagesMap = keyBy( - await this.service.views.getThreadsFirstMessages(messages.map(a => a.thread_id)), - item => item.id, - ); + messages.push(msg); + if (messages.length == limit) { + break; + } + } - const resources = messages.map((resource: Message) => { - const firstMessage = firstMessagesMap[resource.thread_id]; - return { - ...firstMessage, - last_replies: resource.id != firstMessage.id ? [resource] : [], - } as MessageWithReplies; - }); + const extendedMessages = []; + for (const message of messages) { + const extended = { + ...(await gr.services.messages.messages.includeUsersInMessage(message, context)), + channel: await gr.services.channels.channels.get( + { + company_id: message.cache?.company_id, + workspace_id: message.cache?.workspace_id, + id: message.cache?.channel_id, + }, + context, + ), + }; + extendedMessages.push(extended); + } - return { resources }; + return { + resources: extendedMessages, + ...(lastPageToken && { + next_page_token: lastPageToken, + }), + }; } + + searchFiles = searchFiles; } export interface MessageViewListQueryParameters @@ -142,6 +272,11 @@ export interface MessageViewListQueryParameters export interface MessageViewSearchQueryParameters extends PaginationQueryParameters { q: string; + workspace_id: string; + channel_id: string; + sender: string; + has_files: boolean; + has_medias: boolean; } function getChannelViewExecutionContext( @@ -166,3 +301,18 @@ function getChannelViewExecutionContext( }, }; } + +export function getCompanyExecutionContext( + request: FastifyRequest<{ + Params: { company_id: string }; + }>, +): CompanyExecutionContext { + return { + user: request.currentUser, + company: { id: request.params.company_id }, + url: request.url, + method: request.routerMethod, + reqId: request.id, + transport: "http", + }; +} diff --git a/twake/backend/node/src/services/messages/web/controllers/views/recent-files.ts b/twake/backend/node/src/services/messages/web/controllers/views/recent-files.ts new file mode 100644 index 0000000000..4d1eeec603 --- /dev/null +++ b/twake/backend/node/src/services/messages/web/controllers/views/recent-files.ts @@ -0,0 +1,32 @@ +import { FastifyRequest } from "fastify"; +import { Pagination } from "../../../../../core/platform/framework/api/crud-service"; +import { PaginationQueryParameters, ResourceListResponse } from "../../../../../utils/types"; +import gr from "../../../../global-resolver"; +import { PublicFile } from "../../../../../services/files/entities/file"; +import { getCompanyExecutionContext } from "../views"; +import { FileSearchResult } from "./search-files"; + +export default async ( + request: FastifyRequest<{ + Params: { company_id: string }; + Querystring: { + page_token: string; + limit?: string; + type?: "user_upload" | "user_download"; + media?: "media_only" | "file_only"; + }; + }>, +): Promise> => { + const userFiles = await gr.services.messages.views.listUserMarkedFiles( + request.currentUser.id, + request.query.type || "both", + request.query.media || "both", + getCompanyExecutionContext(request), + new Pagination(request.query.page_token, String(request.query.limit || 100)), + ); + + return { + resources: userFiles.getEntities().filter(a => a?.metadata?.external_id) as FileSearchResult[], + next_page_token: userFiles?.nextPage?.page_token, + }; +}; diff --git a/twake/backend/node/src/services/messages/web/controllers/views/search-files.ts b/twake/backend/node/src/services/messages/web/controllers/views/search-files.ts new file mode 100644 index 0000000000..1960b4d05a --- /dev/null +++ b/twake/backend/node/src/services/messages/web/controllers/views/search-files.ts @@ -0,0 +1,216 @@ +import { FastifyRequest } from "fastify"; +import { ListResult, Pagination } from "../../../../../core/platform/framework/api/crud-service"; +import { MessageFile } from "../../../../../services/messages/entities/message-files"; +import { Message } from "../../../../../services/messages/entities/messages"; +import { + ChannelViewExecutionContext, + FlatFileFromMessage, +} from "../../../../../services/messages/types"; +import { UserObject } from "../../../../../services/user/web/types"; +import { PaginationQueryParameters, ResourceListResponse } from "../../../../../utils/types"; +import { formatUser } from "../../../../../utils/users"; +import gr from "../../../../global-resolver"; +import { MessageFileRef } from "../../../../../services/messages/entities/message-file-refs"; +import recentFiles from "./recent-files"; +import { isEmpty } from "lodash"; + +interface MessageViewSearchFilesQueryParameters extends PaginationQueryParameters { + q: string; + workspace_id: string; + channel_id: string; + sender: string; + is_file: boolean; + is_media: boolean; + extension: string; +} + +export type FileSearchResult = MessageFile & { + message: Message; + user: UserObject; + context?: MessageFileRef; +}; + +export default async ( + request: FastifyRequest<{ + Querystring: MessageViewSearchFilesQueryParameters & { + page_token: string; + }; + Params: { + company_id: string; + }; + }>, + context: ChannelViewExecutionContext, +): Promise> => { + const files = await searchFiles(request, context); + + //Include channel in reply everytime + await Promise.all( + files.resources.map((f, i) => { + return (async () => { + const channel = await gr.services.channels.channels.get( + { + id: f.cache.channel_id, + company_id: f.cache.company_id, + workspace_id: f.cache.workspace_id, + }, + context, + ); + files.resources[i] = { ...f, channel } as MessageFile; + })(); + }), + ); + + return files; +}; + +const searchFiles = async ( + request: FastifyRequest<{ + Querystring: MessageViewSearchFilesQueryParameters & { + page_token: string; + }; + Params: { + company_id: string; + }; + }>, + context: ChannelViewExecutionContext, +): Promise> => { + const limit = +request.query.limit || 100; + + if (isEmpty(request.query?.q)) { + if (request.query.channel_id) { + const tmp = await gr.services.messages.views.listChannelFiles( + new Pagination(request.query.page_token, limit.toString()), + { + flat: true, + ...(request.query.is_file ? { file_only: true } : {}), + ...(request.query.is_media ? { media_only: true } : {}), + }, + { + ...context, + channel: { + id: request.query.channel_id, + workspace_id: request.query.workspace_id || context.channel.workspace_id, + company_id: request.params.company_id, + }, + }, + ); + + let resources: FileSearchResult[] = []; + for (let flatFile of tmp.getEntities()) { + flatFile = flatFile as FlatFileFromMessage; + resources.push({ + ...flatFile.file, + message: flatFile.thread, + context: flatFile.context, + user: await formatUser( + await gr.services.users.getCached({ id: flatFile.thread.user_id }), + ), + }); + } + + return { + resources, + next_page_token: tmp.nextPage.page_token, + }; + } else { + return recentFiles({ + ...request, + query: { + ...request.query, + media: request.query.is_media + ? "media_only" + : request.query.is_file + ? "file_only" + : undefined, + }, + }); + } + } + + async function* getNextMessageFiles(initialPageToken?: string): AsyncIterableIterator<{ + msgFile: MessageFile; + pageToken: string; + }> { + let lastPageToken = initialPageToken; + let messageFiles: MessageFile[] = []; + let hasMoreMessageFiles = true; + do { + messageFiles = await gr.services.messages.views + .searchFiles( + new Pagination(lastPageToken, limit.toString()), + { + search: request.query.q, + companyId: request.params.company_id, + workspaceId: request.query.workspace_id, + channelId: request.query.channel_id, + ...(request.query.is_file ? { isFile: true } : {}), + ...(request.query.is_media ? { isMedia: true } : {}), + ...(request.query.sender ? { sender: request.query.sender } : {}), + ...(request.query.extension ? { extension: request.query.extension } : {}), + }, + context, + ) + .then((a: ListResult) => { + lastPageToken = a.nextPage.page_token; + if (!lastPageToken) { + hasMoreMessageFiles = false; + } + return a.getEntities(); + }); + + if (messageFiles.length) { + for (const messageFile of messageFiles) { + yield { msgFile: messageFile, pageToken: lastPageToken }; + } + } else { + hasMoreMessageFiles = false; + } + } while (hasMoreMessageFiles); + } + + let messageFiles = [] as FileSearchResult[]; + let nextPageToken = null; + + for await (const { msgFile, pageToken } of getNextMessageFiles(request.query.page_token)) { + nextPageToken = pageToken; + const getChannelMember = await gr.services.channels.members.getChannelMember( + { id: request.currentUser.id }, + { + company_id: msgFile.cache?.company_id, + workspace_id: msgFile.cache?.workspace_id, + id: msgFile.cache?.channel_id, + }, + 50, + context, + ); + if (!getChannelMember) continue; + + try { + const message = await gr.services.messages.messages.get({ + thread_id: msgFile.thread_id, + id: msgFile.message_id, + }); + const user = await formatUser( + await gr.services.users.getCached({ id: msgFile.cache?.user_id }), + ); + + messageFiles.push({ ...msgFile, user, message }); + if (messageFiles.length == limit) { + break; + } + } catch (e) { + continue; + } + } + + messageFiles = messageFiles + .filter(mf => mf.message.subtype !== "deleted") + .filter(a => a?.metadata?.external_id); + + return { + resources: messageFiles, + ...(nextPageToken && { + next_page_token: nextPageToken, + }), + }; +}; diff --git a/twake/backend/node/src/services/messages/web/index.ts b/twake/backend/node/src/services/messages/web/index.ts index 7c52121b48..603b828f0b 100644 --- a/twake/backend/node/src/services/messages/web/index.ts +++ b/twake/backend/node/src/services/messages/web/index.ts @@ -1,14 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import { MessageServiceAPI } from "../api"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: MessageServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /internal/services/messages/v1 routes"); diff --git a/twake/backend/node/src/services/messages/web/routes.ts b/twake/backend/node/src/services/messages/web/routes.ts index 575730216b..0b595b0fff 100644 --- a/twake/backend/node/src/services/messages/web/routes.ts +++ b/twake/backend/node/src/services/messages/web/routes.ts @@ -1,173 +1,227 @@ import { FastifyInstance, FastifyPluginCallback } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import { MessageServiceAPI } from "../api"; import { - ThreadsController, MessagesController, + ThreadsController, UserBookmarksController, ViewsController, } from "./controllers"; - -const routes: FastifyPluginCallback<{ service: MessageServiceAPI; realtime: RealtimeServiceAPI }> = - (fastify: FastifyInstance, options, next) => { - const threadsController = new ThreadsController(options.service); - const messagesController = new MessagesController(options.realtime, options.service); - const userBookmarksController = new UserBookmarksController(options.realtime, options.service); - const viewsController = new ViewsController(options.realtime, options.service); - - /** - * User bookmarks collection - */ - fastify.route({ - method: "GET", - url: "/companies/:company_id/preferences/bookmarks", - preValidation: [fastify.authenticate], - handler: userBookmarksController.list.bind(userBookmarksController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/preferences/bookmarks/:id", - preValidation: [fastify.authenticate], - handler: userBookmarksController.save.bind(userBookmarksController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/preferences/bookmarks", - preValidation: [fastify.authenticate], - handler: userBookmarksController.save.bind(userBookmarksController), - }); - - fastify.route({ - method: "DELETE", - url: "/companies/:company_id/preferences/bookmarks/:id", - preValidation: [fastify.authenticate], - handler: userBookmarksController.delete.bind(userBookmarksController), - }); - - /** - * Threads creation route - */ - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads", - preValidation: [fastify.authenticate], - handler: threadsController.save.bind(threadsController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id", - preValidation: [fastify.authenticate], - handler: threadsController.save.bind(threadsController), - }); - - /** - * In threads message collection - */ - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages", - preValidation: [fastify.authenticate], - handler: messagesController.save.bind(messagesController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id", - preValidation: [fastify.authenticate], - handler: messagesController.save.bind(messagesController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id", - preValidation: [fastify.authenticate], - handler: messagesController.get.bind(messagesController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/threads/:thread_id/messages", - preValidation: [fastify.authenticate], - handler: messagesController.list.bind(messagesController), - }); - - fastify.route({ - method: "DELETE", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id", - preValidation: [fastify.authenticate], - handler: messagesController.forceDelete.bind(messagesController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id/reaction", - preValidation: [fastify.authenticate], - handler: messagesController.reaction.bind(messagesController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id/bookmark", - preValidation: [fastify.authenticate], - handler: messagesController.bookmark.bind(messagesController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id/pin", - preValidation: [fastify.authenticate], - handler: messagesController.pin.bind(messagesController), - }); - - fastify.route({ - method: "POST", - url: "/companies/:company_id/threads/:thread_id/messages/:message_id/delete", - preValidation: [fastify.authenticate], - handler: messagesController.delete.bind(messagesController), - }); - - /** - * Views routes - */ - fastify.route({ - method: "GET", - url: "/companies/:company_id/workspaces/:workspace_id/channels/:channel_id/feed", - preValidation: [fastify.authenticate], - handler: viewsController.list.bind(viewsController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/files", - preValidation: [fastify.authenticate], - handler: viewsController.list.bind(viewsController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/bookmarks", - preValidation: [fastify.authenticate], - handler: viewsController.list.bind(viewsController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/inbox", - preValidation: [fastify.authenticate], - handler: viewsController.list.bind(viewsController), - }); - - fastify.route({ - method: "GET", - url: "/companies/:company_id/search", - preValidation: [fastify.authenticate], - handler: viewsController.search.bind(viewsController), - }); - - next(); - }; +import { MessagesFilesController } from "./controllers/messages-files"; +import { listUserFiles } from "./schemas"; + +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const threadsController = new ThreadsController(); + const messagesController = new MessagesController(); + const userBookmarksController = new UserBookmarksController(); + const viewsController = new ViewsController(); + const messagesFilesController = new MessagesFilesController(); + + /** + * User bookmarks collection + */ + fastify.route({ + method: "GET", + url: "/companies/:company_id/preferences/bookmarks", + preValidation: [fastify.authenticate], + handler: userBookmarksController.list.bind(userBookmarksController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/preferences/bookmarks/:id", + preValidation: [fastify.authenticate], + handler: userBookmarksController.save.bind(userBookmarksController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/preferences/bookmarks", + preValidation: [fastify.authenticate], + handler: userBookmarksController.save.bind(userBookmarksController), + }); + + fastify.route({ + method: "DELETE", + url: "/companies/:company_id/preferences/bookmarks/:id", + preValidation: [fastify.authenticate], + handler: userBookmarksController.delete.bind(userBookmarksController), + }); + + /** + * Threads creation route + */ + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads", + preValidation: [fastify.authenticate], + handler: threadsController.save.bind(threadsController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id", + preValidation: [fastify.authenticate], + handler: threadsController.save.bind(threadsController), + }); + + /** + * In threads message collection + */ + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages", + preValidation: [fastify.authenticate], + handler: messagesController.save.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id", + preValidation: [fastify.authenticate], + handler: messagesController.save.bind(messagesController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id", + preValidation: [fastify.authenticate], + handler: messagesController.get.bind(messagesController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/threads/:thread_id/messages", + preValidation: [fastify.authenticate], + handler: messagesController.list.bind(messagesController), + }); + + fastify.route({ + method: "DELETE", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id", + preValidation: [fastify.authenticate], + handler: messagesController.forceDelete.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/reaction", + preValidation: [fastify.authenticate], + handler: messagesController.reaction.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/bookmark", + preValidation: [fastify.authenticate], + handler: messagesController.bookmark.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/pin", + preValidation: [fastify.authenticate], + handler: messagesController.pin.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/download/:message_file_id", + preValidation: [fastify.authenticate], + handler: messagesController.download.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/delete", + preValidation: [fastify.authenticate], + handler: messagesController.delete.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/threads/:thread_id/messages/:message_id/deletelink", + preValidation: [fastify.authenticate], + handler: messagesController.deleteLinkPreview.bind(messagesController), + }); + + fastify.route({ + method: "POST", + url: "/companies/:company_id/workspaces/:workspace_id/threads/read", + preValidation: [fastify.authenticate], + handler: messagesController.read.bind(messagesController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/workspaces/:workspace_id/threads/:thread_id/messages/:message_id/seen", + preValidation: [fastify.authenticate], + handler: messagesController.seenBy.bind(messagesController), + }); + + /** + * Views routes + */ + fastify.route({ + method: "GET", + url: "/companies/:company_id/workspaces/:workspace_id/channels/:channel_id/feed", + preValidation: [fastify.authenticate], + handler: viewsController.feed.bind(viewsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/files", + preValidation: [fastify.authenticate], + schema: listUserFiles, + handler: viewsController.files.bind(viewsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/bookmarks", + preValidation: [fastify.authenticate], + handler: viewsController.bookmarks.bind(viewsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/inbox", + preValidation: [fastify.authenticate], + handler: viewsController.inbox.bind(viewsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/search", + preValidation: [fastify.authenticate], + handler: viewsController.search.bind(viewsController), + }); + + fastify.route({ + method: "GET", + url: "/companies/:company_id/files/search", + preValidation: [fastify.authenticate], + handler: viewsController.searchFiles.bind(viewsController), + }); + + /** + * Messages files routes + */ + + fastify.route({ + method: "GET", + url: "/companies/:company_id/messages/:message_id/files/:message_file_id", + preValidation: [fastify.authenticate], + handler: messagesFilesController.getMessageFile.bind(messagesFilesController), + }); + + fastify.route({ + method: "DELETE", + url: "/companies/:company_id/messages/:message_id/files/:message_file_id", + preValidation: [fastify.authenticate], + handler: messagesFilesController.deleteMessageFile.bind(messagesFilesController), + }); + + next(); +}; export default routes; diff --git a/twake/backend/node/src/services/messages/web/schemas.ts b/twake/backend/node/src/services/messages/web/schemas.ts new file mode 100644 index 0000000000..db5db9b82a --- /dev/null +++ b/twake/backend/node/src/services/messages/web/schemas.ts @@ -0,0 +1,37 @@ +const publicFileSchema = { + type: "object", + properties: { + id: { type: "string" }, + user_id: { type: "string" }, + company_id: { type: "string" }, + application_id: { type: "string" }, + updated_at: { type: "number" }, + created_at: { type: "number" }, + metadata: { type: "object", additionalProperties: true }, + thumbnails: { type: "array" }, + upload_data: { type: "object", additionalProperties: true }, + user: { type: "object", additionalProperties: true, nullable: true }, + context: { type: "object", additionalProperties: true, nullable: true }, + }, +}; + +export const listUserFiles = { + request: { + properties: { + type: { type: "string", enum: ["user_upload", "user_download"] }, + page_token: { type: "string" }, + limit: { type: "number" }, + }, + required: ["type"], + }, + response: { + "2xx": { + type: "object", + properties: { + resources: { type: "array", items: publicFileSchema }, + next_page_token: { type: "string" }, + }, + required: ["resources"], + }, + }, +}; diff --git a/twake/backend/node/src/services/notifications/api.ts b/twake/backend/node/src/services/notifications/api.ts deleted file mode 100644 index 73b729e06d..0000000000 --- a/twake/backend/node/src/services/notifications/api.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { - CRUDService, - ListResult, - SaveResult, -} from "../../core/platform/framework/api/crud-service"; -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; -import { - ChannelMemberNotificationPreference, - ChannelMemberNotificationPreferencePrimaryKey, - ChannelThreadUsers, - ChannelThreadUsersPrimaryKey, - UserNotificationBadge, - UserNotificationBadgePrimaryKey, - UserNotificationPreferences, - UserNotificationPreferencesPrimaryKey, -} from "./entities"; -import { NotificationExecutionContext } from "./types"; -import { PubsubHandler } from "../../core/platform/services/pubsub/api"; -import { NotificationEngine } from "./services/engine"; -import { NotificationPreferencesService } from "./services/preferences/service"; -import { MobilePushService } from "./services/mobile-push/service"; - -export interface NotificationServiceAPI extends TwakeServiceProvider, Initializable { - badges: UserNotificationBadgeServiceAPI; - channelPreferences: ChannelMemberPreferencesServiceAPI; - channelThreads: ChannelThreadUsersServiceAPI; - engine: NotificationEngine; - notificationPreferences: NotificationPreferencesService; - mobilePush: MobilePushService; -} - -export interface UserNotificationBadgeServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService< - UserNotificationBadge, - UserNotificationBadgePrimaryKey, - NotificationExecutionContext - > { - /** - * List companies with badge for user. - * @param companies - * @param user - */ - listForUserPerCompanies(user_id: string): Promise>; - - /** - * List badges for user in a company. The filter allows to get the badges per workspace/channel/thread when they are defined - * @param company - * @param user - * @param filter - */ - listForUser( - company_id: string, - user_id: string, - filter: Pick, - ): Promise>; - - /** - * Remove all the badges in channel for user - * @param - */ - removeUserChannelBadges( - filter: Pick< - UserNotificationBadgePrimaryKey, - "workspace_id" | "company_id" | "channel_id" | "user_id" - >, - ): Promise; -} - -export interface ChannelMemberPreferencesServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService< - ChannelMemberNotificationPreference, - ChannelMemberNotificationPreferencePrimaryKey, - NotificationExecutionContext - > { - /** - * Get the notification preferences in a channel for a set of users - * - * @param channel The channel to get user preferences from - * @param users The list of users to get preferences from. When not defined, get the preferences for all users in the channel. - */ - getChannelPreferencesForUsers( - channel: Pick, - users?: string[], - lastRead?: { - lessThan: number; - }, - ): Promise>; - - /** - * Update the last read value for given user/channel. Will not create the preference if not exists - * - * @param channel - * @param user - * @param lastRead - */ - updateLastRead( - channel: Pick, - user: string, - lastRead: number, - ): Promise; -} - -export interface ChannelThreadUsersServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - /** - * Save a list of users involved in a thread - * - * @param users List of users to save - */ - bulkSave(users: ChannelThreadUsers[]): Promise>; - - /** - * Get all the users involved in a thread - * - * @param pk The thread to get users from - */ - getUsersInThread(pk: ChannelThreadUsersPrimaryKey): Promise>; -} - -export interface UserNotificationPreferencesAPI - extends TwakeServiceProvider, - Initializable, - CRUDService< - UserNotificationPreferences, - UserNotificationPreferencesPrimaryKey, - NotificationExecutionContext - > { - /** - * Get the user notification preferences - * - * @param workspace_id - * @param company_id - * @param user_id - * @param filter - */ - listPreferences( - workspace_id: string | "all", - company_id: string | "all", - user_id: string, - filter: Pick, - ): Promise>; - - /** - * Save the user notification preferences - * - * @param notificationPreferences The preference entity to save - */ - savePreferences( - notificationPreferences: UserNotificationPreferences, - ): Promise>; -} - -/** - * A notification hander is in charge of processing a notification from the pubsub layer and then optionally produces something to be consumed by another handler somewhere in the platform. - */ -export interface NotificationPubsubHandler - extends PubsubHandler { - readonly service: NotificationServiceAPI; -} diff --git a/twake/backend/node/src/services/notifications/entities/index.ts b/twake/backend/node/src/services/notifications/entities/index.ts index 4ebbb256e3..bb1e7ead79 100644 --- a/twake/backend/node/src/services/notifications/entities/index.ts +++ b/twake/backend/node/src/services/notifications/entities/index.ts @@ -18,10 +18,3 @@ export { TYPE as UserNotificationBadgeType, getInstance as getUserNotificationBadgeInstance, } from "./user-notification-badges"; - -export { - UserNotificationPreferences, - UserNotificationPreferencesPrimaryKey, - TYPE as UserNotificationPreferencesType, - getInstance as getUserNotificationPreferencesInstance, -} from "./user-notifications-preferences"; diff --git a/twake/backend/node/src/services/notifications/entities/user-notification-badges.ts b/twake/backend/node/src/services/notifications/entities/user-notification-badges.ts index 4a49e953aa..fb19ee471d 100644 --- a/twake/backend/node/src/services/notifications/entities/user-notification-badges.ts +++ b/twake/backend/node/src/services/notifications/entities/user-notification-badges.ts @@ -63,6 +63,9 @@ export class UserNotificationBadge { @Type(() => String) @Column("id", "uuid") id: string = uuidv4(); + + @Column("mention_type", "string") + mention_type: "reply" | "global" | "me" | "unread" | null = "me"; } export type UserNotificationBadgePrimaryKey = Pick< diff --git a/twake/backend/node/src/services/notifications/entities/user-notification-digest.ts b/twake/backend/node/src/services/notifications/entities/user-notification-digest.ts new file mode 100644 index 0000000000..cbbcfdde7c --- /dev/null +++ b/twake/backend/node/src/services/notifications/entities/user-notification-digest.ts @@ -0,0 +1,43 @@ +import { Type } from "class-transformer"; +import { merge } from "lodash"; +import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; + +export const TYPE = "user_notification_digest"; +/** + * Table user-notification-digest + */ +@Entity(TYPE, { + primaryKey: [["company_id"], "user_id"], + type: TYPE, +}) +export class UserNotificationDigest { + /** + * UUIDv4 + * Primary key / partition key + */ + @Type(() => String) + @Column("company_id", "uuid") + company_id: string; + + /** + * UUIDv4 + */ + @Type(() => String) + @Column("user_id", "uuid") + user_id: string; + + @Column("created_at", "number") + created_at: number; + + @Column("deliver_at", "number") + deliver_at: number; +} + +export type UserNotificationDigestPrimaryKey = Pick< + UserNotificationDigest, + "user_id" | "company_id" +>; + +export function getInstance(digest: UserNotificationDigest): UserNotificationDigest { + return merge(new UserNotificationDigest(), digest); +} diff --git a/twake/backend/node/src/services/notifications/entities/user-notifications-preferences.ts b/twake/backend/node/src/services/notifications/entities/user-notifications-preferences.ts deleted file mode 100644 index 4b0585fe14..0000000000 --- a/twake/backend/node/src/services/notifications/entities/user-notifications-preferences.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; -import { Type } from "class-transformer"; -import { merge } from "lodash"; - -export const TYPE = "user_notification_preferences"; - -/** - * Table user-notification-preferences - */ -@Entity(TYPE, { - primaryKey: [["user_id"], "company_id", "workspace_id"], - type: TYPE, -}) -export class UserNotificationPreferences { - /** - * UUIDv4 - * Primary key / partition key - */ - @Column("user_id", "string") - user_id: string; - - /** - * UUIDv4 - * Partition key - */ - @Column("company_id", "string") - company_id: string | "all"; - - /** - * UUIDv4 - * Partition key - */ - @Column("workspace_id", "string") - workspace_id: string | "all"; - - @Column("preferences", "encoded_json") - preferences: { - highlight_words: string[]; - night_break: { - enable: boolean; - from: number; - to: number; - }; - private_message_content: boolean; - mobile_notifications: "never" | "when_inactive" | "always"; - email_notifications_delay: number; //0: never send email, 1 and more in minutes from first unread notification - deactivate_notifications_until: number; - notification_sound: "default" | "none" | string; - }; -} - -export type UserNotificationPreferencesPrimaryKey = Pick< - UserNotificationPreferences, - "company_id" | "user_id" | "workspace_id" ->; - -export function getInstance(preferences: UserNotificationPreferences): UserNotificationPreferences { - return merge(new UserNotificationPreferences(), preferences); -} diff --git a/twake/backend/node/src/services/notifications/index.ts b/twake/backend/node/src/services/notifications/index.ts index 0d8e1a4025..10cbb15736 100644 --- a/twake/backend/node/src/services/notifications/index.ts +++ b/twake/backend/node/src/services/notifications/index.ts @@ -1,42 +1,22 @@ +import { Prefix, TwakeService } from "../../core/platform/framework"; import WebServerAPI from "../../core/platform/services/webserver/provider"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { NotificationServiceAPI } from "./api"; -import { getService } from "./services"; -import web from "./web/index"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import UserServiceAPI from "../user/api"; -import { PushServiceAPI } from "../../core/platform/services/push/api"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; +import web from "./web"; @Prefix("/internal/services/notifications/v1") -@Consumes(["webserver", "database", "pubsub", "user", "push", "realtime"]) -export default class NotificationService extends TwakeService { +export default class NotificationService extends TwakeService { version = "1"; name = "notifications"; - service: NotificationServiceAPI; - user: UserServiceAPI; - - api(): NotificationServiceAPI { - return this.service; - } public async doInit(): Promise { const fastify = this.context.getProvider("webserver").getServer(); - const database = this.context.getProvider("database"); - const pubsub = this.context.getProvider("pubsub"); - const push = this.context.getProvider("push"); - const user = await this.context.getProvider("user").init(); - const realtime = await this.context.getProvider("realtime"); - - this.service = getService(database, pubsub, push, user); - await this.service?.init(this.context); - fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + web(instance, { prefix: this.prefix }); next(); }); - return this; } + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/notifications/notifiers/mobile-push.ts b/twake/backend/node/src/services/notifications/notifiers/mobile-push.ts index 129d1a16cd..2d8e7ca4ab 100644 --- a/twake/backend/node/src/services/notifications/notifiers/mobile-push.ts +++ b/twake/backend/node/src/services/notifications/notifiers/mobile-push.ts @@ -1,5 +1,5 @@ import { logger } from "../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; +import { MessageQueueServiceAPI } from "../../../core/platform/services/message-queue/api"; import { Notifier } from "."; const TOPIC = "notification:push:mobile"; @@ -7,22 +7,22 @@ const TOPIC = "notification:push:mobile"; export class MobilePushNotifier implements Notifier { private static instance: MobilePushNotifier; - static get(pubsub: PubsubServiceAPI): Notifier { + static get(messageQueue: MessageQueueServiceAPI): Notifier { if (!MobilePushNotifier.instance) { - MobilePushNotifier.instance = new MobilePushNotifier(pubsub); + MobilePushNotifier.instance = new MobilePushNotifier(messageQueue); } return MobilePushNotifier.instance; } - private constructor(private pubsub: PubsubServiceAPI) {} + private constructor(private messageQueue: MessageQueueServiceAPI) {} async notify(user: string, message: Message): Promise { logger.info(`MobilePushNotifier - Push to mobile ${user}`); logger.debug(`MobilePushNotifier - Push to mobile ${user}, ${JSON.stringify(message)}`); try { - await this.pubsub.publish(TOPIC, { + await this.messageQueue.publish(TOPIC, { data: message, }); } catch (err) { diff --git a/twake/backend/node/src/services/notifications/services/badges/index.ts b/twake/backend/node/src/services/notifications/services/badges/index.ts deleted file mode 100644 index 6ed8c4686c..0000000000 --- a/twake/backend/node/src/services/notifications/services/badges/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import UserServiceAPI from "../../../../services/user/api"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { UserNotificationBadgeServiceAPI } from "../../api"; -import { UserNotificationBadgeService } from "./service"; - -export function getService( - databaseService: DatabaseServiceAPI, - userService: UserServiceAPI, -): UserNotificationBadgeServiceAPI { - return new UserNotificationBadgeService(databaseService, userService); -} diff --git a/twake/backend/node/src/services/notifications/services/badges/service.ts b/twake/backend/node/src/services/notifications/services/badges/service.ts deleted file mode 100644 index b2de3d564a..0000000000 --- a/twake/backend/node/src/services/notifications/services/badges/service.ts +++ /dev/null @@ -1,154 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import { RealtimeDeleted, RealtimeSaved, TwakeContext } from "../../../../core/platform/framework"; -import { ResourcePath } from "../../../../core/platform/services/realtime/types"; -import { - SaveResult, - DeleteResult, - ListResult, - OperationType, - Paginable, - CrudExeption, - Pagination, -} from "../../../../core/platform/framework/api/crud-service"; -import { UserNotificationBadgeServiceAPI } from "../../api"; -import { - getUserNotificationBadgeInstance, - UserNotificationBadge, - UserNotificationBadgePrimaryKey, - UserNotificationBadgeType, -} from "../../entities"; -import { NotificationExecutionContext } from "../../types"; -import { getNotificationRoomName } from "../realtime"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { pick } from "lodash"; -import _ from "lodash"; -import UserServiceAPI from "../../../../services/user/api"; - -export class UserNotificationBadgeService implements UserNotificationBadgeServiceAPI { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI, private userService: UserServiceAPI) {} - - async init(context: TwakeContext): Promise { - this.repository = await this.database.getRepository( - UserNotificationBadgeType, - UserNotificationBadge, - ); - - return this; - } - - async get(pk: UserNotificationBadgePrimaryKey): Promise { - return await this.repository.findOne(pk); - } - - @RealtimeSaved((badge, context) => { - return [ - { - room: ResourcePath.get(getNotificationRoomName(badge.user_id)), - }, - ]; - }) - async save( - badge: UserNotificationBadge, - options: SaveOptions, - context: NotificationExecutionContext, - ): Promise> { - await this.repository.save(getUserNotificationBadgeInstance(badge)); - - return new SaveResult(UserNotificationBadgeType, badge, OperationType.CREATE); - } - - @RealtimeDeleted((badge, context) => { - return [ - { - room: ResourcePath.get(getNotificationRoomName(badge.user_id)), - }, - ]; - }) - async delete( - pk: UserNotificationBadgePrimaryKey, - context?: NotificationExecutionContext, - ): Promise> { - await this.repository.remove(pk as UserNotificationBadge); - - return new DeleteResult(UserNotificationBadgeType, pk as UserNotificationBadge, true); - } - - list(): Promise> { - throw new Error("Not implemented"); - } - - async listForUserPerCompanies(user_id: string): Promise> { - //We remove all badge from current company as next block will create dupicates - const companies_ids = (await this.userService.companies.getAllForUser(user_id)).map( - gu => gu.group_id, - ); - - let result: UserNotificationBadge[] = []; - let type = ""; - for (const company_id of companies_ids) { - const find = await this.repository.find( - { - company_id, - user_id, - }, - { - pagination: new Pagination("", "1"), - }, - ); - type = find.type; - result = result.concat(find.getEntities()); - } - - return new ListResult(type, result); - } - - listForUser( - company_id: string, - user_id: string, - filter: Pick, - ): Promise> { - if (!company_id || !user_id) { - throw CrudExeption.badRequest("company_id and user_id are required"); - } - - return this.repository.find({ - ...{ - company_id, - user_id, - }, - ...pick(filter, ["workspace_id", "channel_id", "thread_id"]), - }); - } - - /** - * FIXME: This is a temporary implementation which is sending as many websocket notifications as there are badges to remove - * A better implementation will be to do a bulk delete and have a single websocket notification event - * @param filter - */ - async removeUserChannelBadges( - filter: Pick< - UserNotificationBadgePrimaryKey, - "workspace_id" | "company_id" | "channel_id" | "user_id" - >, - ): Promise { - const badges = ( - await this.repository.find( - _.pick(filter, ["workspace_id", "company_id", "channel_id", "user_id"]), - ) - ).getEntities(); - - return ( - await Promise.all( - badges.map(async badge => { - try { - return (await this.delete(badge)).deleted; - } catch (err) {} - }), - ) - ).filter(Boolean).length; - } -} diff --git a/twake/backend/node/src/services/notifications/services/bages.ts b/twake/backend/node/src/services/notifications/services/bages.ts new file mode 100644 index 0000000000..bf27821112 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/bages.ts @@ -0,0 +1,302 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + Initializable, + RealtimeDeleted, + RealtimeSaved, + TwakeContext, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import { + CrudException, + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Pagination, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { + getUserNotificationBadgeInstance, + UserNotificationBadge, + UserNotificationBadgePrimaryKey, + UserNotificationBadgeType, +} from "../entities"; +import { NotificationExecutionContext } from "../types"; +import { getNotificationRoomName } from "./realtime"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import gr from "../../global-resolver"; +import _, { pick, uniq } from "lodash"; + +export class UserNotificationBadgeService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(context: TwakeContext): Promise { + this.repository = await gr.database.getRepository( + UserNotificationBadgeType, + UserNotificationBadge, + ); + + return this; + } + + async get( + pk: UserNotificationBadgePrimaryKey, + context: ExecutionContext, + ): Promise { + return await this.repository.findOne(pk, {}, context); + } + + @RealtimeSaved((badge, context) => { + return [ + { + room: ResourcePath.get(getNotificationRoomName(badge.user_id)), + }, + ]; + }) + async save( + badge: UserNotificationBadge, + context: ExecutionContext, + ): Promise> { + //Initiate the digest + await gr.services.notifications.digest.putBadge(badge); + + await this.repository.save(getUserNotificationBadgeInstance(badge), context); + return new SaveResult(UserNotificationBadgeType, badge, OperationType.CREATE); + } + + @RealtimeDeleted((badge, context) => { + return [ + { + room: ResourcePath.get(getNotificationRoomName(badge.user_id)), + }, + ]; + }) + async delete( + pk: UserNotificationBadgePrimaryKey, + context?: NotificationExecutionContext, + ): Promise> { + //Cancel the current digest as we just read the badges + await gr.services.notifications.digest.cancelDigest(pk.company_id, pk.user_id); + + await this.repository.remove(pk as UserNotificationBadge, context); + return new DeleteResult(UserNotificationBadgeType, pk as UserNotificationBadge, true); + } + + list(): Promise> { + throw new Error("Not implemented"); + } + + async listForUserPerCompanies( + user_id: string, + context: ExecutionContext, + ): Promise> { + //We remove all badge from current company as next block will create dupicates + const companies_ids = (await gr.services.companies.getAllForUser(user_id)).map( + gu => gu.group_id, + ); + + let result: UserNotificationBadge[] = []; + let type = ""; + for (const company_id of companies_ids) { + const find = await this.repository.find( + { + company_id, + user_id, + }, + { + pagination: new Pagination("", "1"), + }, + context, + ); + type = find.type; + result = result.concat(find.getEntities()); + } + + const badges = new ListResult(type, result); + await this.ensureBadgesAreReachable(badges, context); + + return badges; + } + + async listForUser( + company_id: string, + user_id: string, + filter: Pick, + context?: ExecutionContext, + ): Promise> { + if (!company_id || !user_id) { + throw CrudException.badRequest("company_id and user_id are required"); + } + + //Cancel the current digest as we just read the badges + await gr.services.notifications.digest.cancelDigest(company_id, user_id); + + const badges = await this.repository.find( + { + ...{ + company_id, + user_id, + }, + ...pick(filter, ["workspace_id", "channel_id", "thread_id"]), + }, + {}, + context, + ); + + await this.ensureBadgesAreReachable(badges, context); + + return badges; + } + + // This will ensure we are still in the channels and if not, we'll remove the badge + // We need to also ensure more than that + // - Are we in the workspace? + // - Are we in the company? + async ensureBadgesAreReachable( + badges: ListResult, + context?: ExecutionContext, + ): Promise> { + if (badges.getEntities().length === 0) { + return badges; + } + + const userId = badges.getEntities()[0].user_id; + + const channels = uniq(badges.getEntities().map(r => r.channel_id)); + for (const channelId of channels) { + const someBadge = badges.getEntities().find(b => b.channel_id === channelId); + const channelMemberPk = { + company_id: someBadge.company_id, + workspace_id: someBadge.workspace_id, + channel_id: channelId, + user_id: userId, + }; + const context = { + user: { id: channelMemberPk.user_id, server_request: true }, + channel: { id: channelId, ...channelMemberPk }, + }; + const exists = + (await gr.services.channels.channels.get( + { + id: channelId, + ..._.pick(channelMemberPk, "company_id", "workspace_id"), + }, + context, + )) && (await gr.services.channels.members.get(channelMemberPk, context)); + if (!exists) { + for (const badge of badges.getEntities()) { + if (badge.channel_id === channelId) this.removeUserChannelBadges(badge, context); + } + badges.filterEntities(b => b.channel_id !== channelId); + } + } + + const badgePerWorkspace = _.uniqBy(badges.getEntities(), r => r.workspace_id); + for (const badge of badgePerWorkspace) { + const workspaceId = badge.workspace_id; + const companyId = badge.company_id; + if (!workspaceId || workspaceId === "direct") { + continue; + } + try { + const exists = + (await gr.services.workspaces.get({ + id: workspaceId, + company_id: companyId, + })) && + (await gr.services.workspaces.getUser({ + workspaceId, + userId, + })); + if (!exists) { + await gr.services.channels.members.ensureUserNotInWorkspaceIsNotInChannel( + { id: userId }, + { id: workspaceId, company_id: companyId }, + context, + ); + for (const badge of badges.getEntities()) { + if (badge.workspace_id === workspaceId) this.removeUserChannelBadges(badge, context); + } + badges.filterEntities(b => b.workspace_id !== workspaceId); + } + } catch (e) {} + } + + return badges; + } + + /** + * FIXME: This is a temporary implementation which is sending as many websocket notifications as there are badges to remove + * A better implementation will be to do a bulk delete and have a single websocket notification event + * @param filter + * @param context + */ + async removeUserChannelBadges( + filter: Pick< + UserNotificationBadgePrimaryKey, + "workspace_id" | "company_id" | "channel_id" | "user_id" + >, + context?: ExecutionContext, + ): Promise { + const badges = ( + await this.repository.find( + _.pick(filter, ["workspace_id", "company_id", "channel_id", "user_id"]), + {}, + context, + ) + ).getEntities(); + + return ( + await Promise.all( + badges.map(async badge => { + try { + return (await this.delete(badge)).deleted; + } catch (err) {} + }), + ) + ).filter(Boolean).length; + } + + /** + * acknowledge a notification and set the message status to delivered. + * + * @param {UserNotificationBadgePrimaryKey} pk - The primary key of the badge to acknowledge + * @param {ExecutionContext} context - The context of the acknowledge + * @returns {Promise} - The result of the acknowledge + */ + async acknowledge( + notification: UserNotificationBadgePrimaryKey & { message_id: string }, + context: ExecutionContext, + ): Promise { + const { message_id, ...pk } = notification; + const badge = await this.repository.findOne(pk, {}, context); + const payload = badge || notification; + + const ThreadExecutionContext = { + company: { + id: payload.company_id, + }, + thread: { + id: payload.thread_id, + }, + message_id, + ...context, + }; + + const result = await gr.services.messages.messages.updateDeliveryStatus( + { + ...payload, + status: "delivered", + }, + ThreadExecutionContext, + ); + + if (result) { + return true; + } + + return false; + } +} diff --git a/twake/backend/node/src/services/notifications/services/channel-preferences.ts b/twake/backend/node/src/services/notifications/services/channel-preferences.ts new file mode 100644 index 0000000000..8fa21c3f3d --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/channel-preferences.ts @@ -0,0 +1,157 @@ +import _ from "lodash"; +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { + ChannelMemberNotificationPreference, + ChannelMemberNotificationPreferencePrimaryKey, +} from "../entities"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { Initializable, logger, TwakeServiceProvider } from "../../../core/platform/framework"; +import gr from "../../global-resolver"; + +const TYPE = "channel_members_notification_preferences"; + +export class ChannelMemberPreferencesServiceImpl implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(): Promise { + this.repository = await gr.database.getRepository( + TYPE, + ChannelMemberNotificationPreference, + ); + + return this; + } + + async save( + entity: ChannelMemberNotificationPreference, + context: ExecutionContext, + ): Promise> { + const pk: ChannelMemberNotificationPreferencePrimaryKey = { + user_id: entity.user_id, + company_id: entity.company_id, + channel_id: entity.channel_id, + }; + + let preference = await this.repository.findOne(pk, {}, context); + + if (!preference) { + preference = new ChannelMemberNotificationPreference(); + preference = _.merge(entity, pk); + } + + preference = _.merge(preference, entity); + + await this.repository.save(preference, context); + + return new SaveResult(TYPE, preference, OperationType.CREATE); + } + + async get( + pk: ChannelMemberNotificationPreferencePrimaryKey, + context: ExecutionContext, + ): Promise { + return await this.repository.findOne(pk, {}, context); + } + + async delete( + pk: ChannelMemberNotificationPreferencePrimaryKey, + context?: ExecutionContext, + ): Promise> { + await this.repository.remove(pk as ChannelMemberNotificationPreference, context); + + return new DeleteResult(TYPE, pk as ChannelMemberNotificationPreference, true); + } + + list(): Promise> { + throw new Error("Not implemented"); + } + + async getChannelPreferencesForUsers( + channelAndCompany: Pick< + ChannelMemberNotificationPreferencePrimaryKey, + "channel_id" | "company_id" + >, + users?: string[] | null, + lastRead?: { + lessThan: number; + }, + context?: ExecutionContext, + ): Promise> { + logger.debug( + `ChannelMemberPreferenceService - Get Channel preferences for users ${JSON.stringify( + users, + )} with lastRead < ${lastRead?.lessThan}`, + ); + const result = await this.repository.find( + users ? { ...channelAndCompany, ...{ user_id: users } } : channelAndCompany, + {}, + context, + ); + + if (result.getEntities().length > 0 && lastRead && lastRead.lessThan) { + result.filterEntities(entity => entity.last_read < lastRead.lessThan); + } + + logger.debug( + `ChannelMemberPreferenceService - Result ${JSON.stringify( + result.getEntities().map(preference => preference.user_id), + )}`, + ); + + return result; + } + + async getChannelPreferencesForUsersFilteredByReadTime( + channelAndCompany: Pick< + ChannelMemberNotificationPreferencePrimaryKey, + "channel_id" | "company_id" + >, + users: string[] = [], + lastRead: number, + context?: ExecutionContext, + ): Promise> { + const result = await this.repository.find( + { ...channelAndCompany, ...{ user_id: users } }, + {}, + context, + ); + + if (result.getEntities().length > 0 && lastRead) { + result.filterEntities(entity => entity.last_read < lastRead); + } + + return result; + } + + async updateLastRead( + channelAndCompany: Pick, + user_id: string, + lastRead: number, + context?: ExecutionContext, + ): Promise { + const pk: ChannelMemberNotificationPreferencePrimaryKey = { + user_id, + company_id: channelAndCompany.company_id, + channel_id: channelAndCompany.channel_id, + }; + + const preference = await this.repository.findOne(pk, {}, context); + + if (!preference) { + return; + } + + preference.last_read = lastRead; + + await this.repository.save(preference, context); + + return preference; + } +} diff --git a/twake/backend/node/src/services/notifications/services/channel-preferences/index.ts b/twake/backend/node/src/services/notifications/services/channel-preferences/index.ts deleted file mode 100644 index 9591bfeefd..0000000000 --- a/twake/backend/node/src/services/notifications/services/channel-preferences/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { ChannelMemberPreferencesServiceAPI } from "../../api"; -import { ChannelMemberPreferencesService } from "./service"; - -export function getService( - databaseService: DatabaseServiceAPI, -): ChannelMemberPreferencesServiceAPI { - return new ChannelMemberPreferencesService(databaseService); -} diff --git a/twake/backend/node/src/services/notifications/services/channel-preferences/service.ts b/twake/backend/node/src/services/notifications/services/channel-preferences/service.ts deleted file mode 100644 index f83c497d70..0000000000 --- a/twake/backend/node/src/services/notifications/services/channel-preferences/service.ts +++ /dev/null @@ -1,148 +0,0 @@ -import _ from "lodash"; -import { - DeleteResult, - ListResult, - SaveResult, - OperationType, -} from "../../../../core/platform/framework/api/crud-service"; -import { - ChannelMemberNotificationPreference, - ChannelMemberNotificationPreferencePrimaryKey, -} from "../../entities"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { ChannelMemberPreferencesServiceAPI } from "../../api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { logger } from "../../../../core/platform/framework"; - -const TYPE = "channel_members_notification_preferences"; - -export class ChannelMemberPreferencesService implements ChannelMemberPreferencesServiceAPI { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI) {} - - async init(): Promise { - this.repository = await this.database.getRepository( - TYPE, - ChannelMemberNotificationPreference, - ); - - return this; - } - - async save( - entity: ChannelMemberNotificationPreference, - ): Promise> { - const pk: ChannelMemberNotificationPreferencePrimaryKey = { - user_id: entity.user_id, - company_id: entity.company_id, - channel_id: entity.channel_id, - }; - - let preference = await this.repository.findOne(pk); - - if (!preference) { - preference = new ChannelMemberNotificationPreference(); - preference = _.merge(entity, pk); - } - - preference = _.merge(preference, entity); - - await this.repository.save(preference); - - return new SaveResult(TYPE, preference, OperationType.CREATE); - } - - async get( - pk: ChannelMemberNotificationPreferencePrimaryKey, - ): Promise { - return await this.repository.findOne(pk); - } - - async delete( - pk: ChannelMemberNotificationPreferencePrimaryKey, - ): Promise> { - await this.repository.remove(pk as ChannelMemberNotificationPreference); - - return new DeleteResult(TYPE, pk as ChannelMemberNotificationPreference, true); - } - - list(): Promise> { - throw new Error("Not implemented"); - } - - async getChannelPreferencesForUsers( - channelAndCompany: Pick< - ChannelMemberNotificationPreferencePrimaryKey, - "channel_id" | "company_id" - >, - users: string[] | null = null, - lastRead: { - lessThan: number; - }, - ): Promise> { - logger.debug( - `ChannelMemberPreferenceService - Get Channel preferences for users ${JSON.stringify( - users, - )} with lastRead < ${lastRead?.lessThan}`, - ); - const result = await this.repository.find( - users ? { ...channelAndCompany, ...{ user_id: users } } : channelAndCompany, - {}, - ); - - if (result.getEntities().length > 0 && lastRead && lastRead.lessThan) { - result.filterEntities(entity => entity.last_read < lastRead.lessThan); - } - - logger.debug( - `ChannelMemberPreferenceService - Result ${JSON.stringify( - result.getEntities().map(preference => preference.user_id), - )}`, - ); - - return result; - } - - async getChannelPreferencesForUsersFilteredByReadTime( - channelAndCompany: Pick< - ChannelMemberNotificationPreferencePrimaryKey, - "channel_id" | "company_id" - >, - users: string[] = [], - lastRead: number, - ): Promise> { - const result = await this.repository.find({ ...channelAndCompany, ...{ user_id: users } }, {}); - - if (result.getEntities().length > 0 && lastRead) { - result.filterEntities(entity => entity.last_read < lastRead); - } - - return result; - } - - async updateLastRead( - channelAndCompany: Pick, - user_id: string, - lastRead: number, - ): Promise { - const pk: ChannelMemberNotificationPreferencePrimaryKey = { - user_id, - company_id: channelAndCompany.company_id, - channel_id: channelAndCompany.channel_id, - }; - - const preference = await this.repository.findOne(pk); - - if (!preference) { - return; - } - - preference.last_read = lastRead; - - await this.repository.save(preference); - - return preference; - } -} diff --git a/twake/backend/node/src/services/notifications/services/channel-thread-users.ts b/twake/backend/node/src/services/notifications/services/channel-thread-users.ts new file mode 100644 index 0000000000..2c490bfc76 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/channel-thread-users.ts @@ -0,0 +1,68 @@ +import { + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import { + ChannelThreadUsers, + ChannelThreadUsersPrimaryKey, + ChannelThreadUsersType, +} from "../entities"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import gr from "../../global-resolver"; +import { Initializable, TwakeServiceProvider } from "../../../core/platform/framework"; + +export class ChannelThreadUsersServiceImpl implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(): Promise { + this.repository = await gr.database.getRepository( + ChannelThreadUsersType, + ChannelThreadUsers, + ); + + return this; + } + + async bulkSave( + entities: ChannelThreadUsers[], + context: ExecutionContext, + ): Promise> { + await this.repository.saveAll(entities, context); + + return new SaveResult(ChannelThreadUsersType, entities, OperationType.CREATE); + } + + async get( + pk: ChannelThreadUsersPrimaryKey, + context: ExecutionContext, + ): Promise { + return await this.repository.findOne(pk, {}, context); + } + + async delete( + pk: ChannelThreadUsersPrimaryKey, + context: ExecutionContext, + ): Promise> { + await this.repository.remove(pk as ChannelThreadUsers, context); + + return new DeleteResult(ChannelThreadUsersType, pk as ChannelThreadUsers, true); + } + + list(): Promise> { + throw new Error("Not implemented"); + } + + async getUsersInThread( + pk: ChannelThreadUsersPrimaryKey, + context: ExecutionContext, + ): Promise> { + if (!pk.company_id || !pk.channel_id || !pk.thread_id) { + throw new Error("Missing required fields"); + } + return this.repository.find(pk, {}, context); + } +} diff --git a/twake/backend/node/src/services/notifications/services/channel-thread-users/index.ts b/twake/backend/node/src/services/notifications/services/channel-thread-users/index.ts deleted file mode 100644 index 3f42b97178..0000000000 --- a/twake/backend/node/src/services/notifications/services/channel-thread-users/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { ChannelThreadUsersServiceAPI } from "../../api"; -import { ChannelThreadUsersService } from "./service"; - -export function getService(databaseService: DatabaseServiceAPI): ChannelThreadUsersServiceAPI { - return new ChannelThreadUsersService(databaseService); -} diff --git a/twake/backend/node/src/services/notifications/services/channel-thread-users/service.ts b/twake/backend/node/src/services/notifications/services/channel-thread-users/service.ts deleted file mode 100644 index 7adfa35245..0000000000 --- a/twake/backend/node/src/services/notifications/services/channel-thread-users/service.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - DeleteResult, - ListResult, - SaveResult, - OperationType, -} from "../../../../core/platform/framework/api/crud-service"; -import { - ChannelThreadUsers, - ChannelThreadUsersPrimaryKey, - ChannelThreadUsersType, -} from "../../entities"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { ChannelThreadUsersServiceAPI } from "../../api"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; - -export class ChannelThreadUsersService implements ChannelThreadUsersServiceAPI { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI) {} - - async init(): Promise { - this.repository = await this.database.getRepository( - ChannelThreadUsersType, - ChannelThreadUsers, - ); - - return this; - } - - async bulkSave(entities: ChannelThreadUsers[]): Promise> { - await this.repository.saveAll(entities); - - return new SaveResult(ChannelThreadUsersType, entities, OperationType.CREATE); - } - - async get(pk: ChannelThreadUsersPrimaryKey): Promise { - return await this.repository.findOne(pk); - } - - async delete(pk: ChannelThreadUsersPrimaryKey): Promise> { - await this.repository.remove(pk as ChannelThreadUsers); - - return new DeleteResult(ChannelThreadUsersType, pk as ChannelThreadUsers, true); - } - - list(): Promise> { - throw new Error("Not implemented"); - } - - async getUsersInThread( - pk: ChannelThreadUsersPrimaryKey, - ): Promise> { - if (!pk.company_id || !pk.channel_id || !pk.thread_id) { - throw new Error("Missing required fields"); - } - return this.repository.find(pk); - } -} diff --git a/twake/backend/node/src/services/notifications/services/digest.ts b/twake/backend/node/src/services/notifications/services/digest.ts new file mode 100644 index 0000000000..55e0603148 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/digest.ts @@ -0,0 +1,168 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { MessageWithReplies } from "../../../services/messages/types"; +import { Initializable, TwakeServiceProvider } from "../../../core/platform/framework"; +import { Paginable, Pagination } from "../../../core/platform/framework/api/crud-service"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { Channel } from "../../../services/channels/entities"; +import { Message } from "../../../services/messages/entities/messages"; +import { UserObject } from "../../../services/user/web/types"; +import Workspace from "../../../services/workspaces/entities/workspace"; +import gr from "../../global-resolver"; +import { UserNotificationBadge } from "../entities"; +import { getInstance, TYPE, UserNotificationDigest } from "../entities/user-notification-digest"; + +export class UserNotificationDigestService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(): Promise { + this.repository = await gr.database.getRepository( + TYPE, + UserNotificationDigest, + ); + + gr.platformServices.cron.schedule( + "*/15 * * * *", + async () => { + //This being multi-node we will try to avoid running them at the exact same time + //Fixme: this is until we find a better solution of course + await new Promise(r => setTimeout(r, 1000 * 60 * Math.random())); + await this.processDigests(); + }, + "Find and process digests", + ); + + return this; + } + + async getDigest(companyId: string, userId: string): Promise { + return await this.repository.findOne({ company_id: companyId, user_id: userId }); + } + + async cancelDigest(companyId: string, userId: string) { + const digest = await this.getDigest(companyId, userId); + if (digest) await this.repository.remove(digest); + } + + async putBadge(badge: UserNotificationBadge): Promise { + const digest = await this.getDigest(badge.company_id, badge.user_id); + let deliver_at = digest?.deliver_at; + if (!deliver_at) { + //Get user preferences to set the deliver at + const preferences = await gr.services.notifications.preferences.getMerged({ + company_id: badge.company_id, + user_id: badge.user_id, + workspace_id: "all", + }); + let emailNotificationsDelay = preferences?.preferences?.email_notifications_delay; + if (emailNotificationsDelay === undefined) emailNotificationsDelay = 15; + if (!emailNotificationsDelay) { + return; + } else { + deliver_at = Date.now() + emailNotificationsDelay * 1000 * 60; + } + } + await this.repository.save( + getInstance({ + company_id: badge.company_id, + user_id: badge.user_id, + created_at: digest?.created_at || Date.now(), + deliver_at, + }), + ); + } + + async processDigests(): Promise { + let digestsPagination: Paginable = new Pagination(null, "100"); + do { + const digests = await this.repository.find({}); + const digestsEntities = digests.getEntities().filter(d => { + return d.deliver_at < Date.now(); + }); + + for (const digest of digestsEntities) { + await this.repository.remove(digest); + } + + for (const digest of digestsEntities) { + await this.processDigest(digest); + } + + digestsPagination = new Pagination(digests.nextPage.page_token, "100"); + } while (digestsPagination.page_token); + } + + async processDigest(digest: UserNotificationDigest): Promise { + const badges = await gr.services.notifications.badges.listForUser( + digest.company_id, + digest.user_id, + {} as any, + ); + + const user = await gr.services.users.get({ id: digest.user_id }); + const company = await gr.services.companies.getCompany({ id: digest.company_id }); + let notifications: { + channel: Channel; + workspace: Workspace; + message: Message & { user: UserObject }; + }[] = []; + let workspaces: { [key: string]: Workspace } = {}; + let channels: { [key: string]: Channel } = {}; + + for (const badge of badges.getEntities()) { + if (!badge.thread_id) continue; + try { + const message = await gr.services.messages.messages.includeUsersInMessageWithReplies( + (await gr.services.messages.messages.get({ + id: badge.thread_id, + thread_id: badge.thread_id, + })) as MessageWithReplies, + ); + + if (message.created_at < digest.created_at - 60 * 1000) continue; + + channels[badge.channel_id] = + channels[badge.channel_id] || + (await gr.services.channels.channels.get({ + company_id: badge.company_id, + workspace_id: badge.workspace_id, + id: badge.channel_id, + })); + + workspaces[badge.workspace_id] = + badge.workspace_id && badge.workspace_id !== "direct" + ? workspaces[badge.workspace_id] || + (await gr.services.workspaces.get({ + company_id: badge.company_id, + id: badge.workspace_id, + })) + : null; + + notifications.push({ + channel: channels[badge.channel_id], + workspace: workspaces[badge.workspace_id], + message: { ...message, user: (message.users || []).find(u => u.id === message.user_id) }, + }); + } catch (e) {} + } + + const etaEntry = { + user, + company, + notifications, + }; + + if (notifications.length > 0) { + const { html, text, subject } = await gr.platformServices.emailPusher.build( + "notification-digest", + user.language, + etaEntry, + ); + await gr.platformServices.emailPusher.send(user.email_canonical, { + subject, + html, + text, + }); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/index.ts b/twake/backend/node/src/services/notifications/services/engine/index.ts index 2fac44379b..96b6fe4ea0 100644 --- a/twake/backend/node/src/services/notifications/services/engine/index.ts +++ b/twake/backend/node/src/services/notifications/services/engine/index.ts @@ -1,6 +1,4 @@ import { Initializable } from "../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; -import { NotificationServiceAPI } from "../../api"; import { MarkChannelAsReadMessageProcessor } from "./processors/mark-channel-as-read"; import { MarkChannelAsUnreadMessageProcessor } from "./processors/mark-channel-as-unread"; import { NewChannelMessageProcessor } from "./processors/new-channel-message"; @@ -9,24 +7,29 @@ import { PushNotificationToUsersMessageProcessor } from "./processors/push-to-us import { LeaveChannelMessageProcessor } from "./processors/channel-member-deleted"; import { JoinChannelMessageProcessor } from "./processors/channel-member-created"; import { UpdateChannelMemberMessageProcessor } from "./processors/channel-member-updated"; +import { PushReactionNotification } from "./processors/reaction-notification"; +import gr from "../../../global-resolver"; /** * The notification engine is in charge of processing data and delivering user notifications on the right place */ export class NotificationEngine implements Initializable { - constructor(private service: NotificationServiceAPI, private pubsub: PubsubServiceAPI) {} - async init(): Promise { - this.pubsub.processor.addHandler(new UpdateChannelMemberMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new JoinChannelMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new LeaveChannelMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new MarkChannelAsReadMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new MarkChannelAsUnreadMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new NewChannelMessageProcessor(this.service)); - this.pubsub.processor.addHandler(new PushNotificationMessageProcessor(this.service)); - this.pubsub.processor.addHandler( - new PushNotificationToUsersMessageProcessor(this.service, this.pubsub), + gr.platformServices.messageQueue.processor.addHandler( + new UpdateChannelMemberMessageProcessor(), + ); + gr.platformServices.messageQueue.processor.addHandler(new JoinChannelMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler(new LeaveChannelMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler(new MarkChannelAsReadMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler( + new MarkChannelAsUnreadMessageProcessor(), + ); + gr.platformServices.messageQueue.processor.addHandler(new NewChannelMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler(new PushNotificationMessageProcessor()); + gr.platformServices.messageQueue.processor.addHandler( + new PushNotificationToUsersMessageProcessor(), ); + gr.platformServices.messageQueue.processor.addHandler(new PushReactionNotification()); return this; } diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created.ts new file mode 100644 index 0000000000..a12e6466a8 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created.ts @@ -0,0 +1,79 @@ +import { + ChannelMemberNotificationPreference, + getNotificationPreferenceInstance, +} from "../../../entities"; +import { logger } from "../../../../../core/platform/framework"; +import { Channel, ChannelMember } from "../../../../channels/entities"; +import gr from "../../../../global-resolver"; +import { NotificationMessageQueueHandler } from "../../../types"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +type JoinChannelMessage = { channel: Channel; member: ChannelMember }; + +export class JoinChannelMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "channel:member:created", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "JoinChannelMessageProcessor"; + + validate(message: JoinChannelMessage): boolean { + return !!(message && message.channel && message.member); + } + + async process(message: JoinChannelMessage, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing join channel message for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + try { + let preference: ChannelMemberNotificationPreference; + + if (Channel.isDirectChannel(message.channel)) { + // Check if the user already have preference for this channel in case he already joined it before + preference = await gr.services.notifications.channelPreferences.get( + { + company_id: message.member.company_id, + channel_id: message.member.channel_id, + user_id: message.member.user_id, + }, + context, + ); + } + + if (preference) { + logger.info( + `${this.name} - Notification preference already exists for user ${message.member.user_id} in direct channel ${message.channel.id}`, + ); + + return; + } + + preference = getNotificationPreferenceInstance({ + channel_id: message.member.channel_id, + company_id: message.member.company_id, + user_id: message.member.user_id, + last_read: message.member.last_access || 0, + preferences: message.member.notification_level, + }); + + await gr.services.notifications.channelPreferences.save(preference, context); + + logger.info( + `${this.name} - Notification preference has been created for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.warn( + { err }, + `${this.name} - Error while creating notification preference from pubsub`, + ); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created/index.ts deleted file mode 100644 index 6259a78039..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-created/index.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { - ChannelMemberNotificationPreference, - getNotificationPreferenceInstance, -} from "../../../../entities"; -import { logger } from "../../../../../../core/platform/framework"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { Channel, ChannelMember } from "../../../../../channels/entities"; - -type JoinChannelMessage = { channel: Channel; member: ChannelMember }; - -export class JoinChannelMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "channel:member:created", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "JoinChannelMessageProcessor"; - - validate(message: JoinChannelMessage): boolean { - return !!(message && message.channel && message.member); - } - - async process(message: JoinChannelMessage): Promise { - logger.info( - `${this.name} - Processing join channel message for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - try { - let preference: ChannelMemberNotificationPreference; - - if (Channel.isDirectChannel(message.channel)) { - // Check if the user already have preference for this channel in case he already joined it before - preference = await this.service.channelPreferences.get({ - company_id: message.member.company_id, - channel_id: message.member.channel_id, - user_id: message.member.user_id, - }); - } - - if (preference) { - logger.info( - `${this.name} - Notification preference already exists for user ${message.member.user_id} in direct channel ${message.channel.id}`, - ); - - return; - } - - preference = getNotificationPreferenceInstance({ - channel_id: message.member.channel_id, - company_id: message.member.company_id, - user_id: message.member.user_id, - last_read: message.member.last_access || 0, - preferences: message.member.notification_level, - }); - - await this.service.channelPreferences.save(preference); - - logger.info( - `${this.name} - Notification preference has been created for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.warn( - { err }, - `${this.name} - Error while creating notification preference from pubsub`, - ); - } - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted.ts new file mode 100644 index 0000000000..fa7c873ddb --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted.ts @@ -0,0 +1,101 @@ +import { assign, merge } from "lodash"; +import { ChannelMemberNotificationPreference, UserNotificationBadge } from "../../../entities"; +import { logger } from "../../../../../core/platform/framework"; +import { Channel, ChannelMember } from "../../../../channels/entities"; +import { isDirectChannel } from "../../../../channels/utils"; +import gr from "../../../../global-resolver"; +import { NotificationMessageQueueHandler } from "../../../types"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +type LeaveChannelMessage = { channel: Channel; member: ChannelMember }; + +export class LeaveChannelMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "channel:member:deleted", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "LeaveChannelMessageProcessor"; + + validate(message: LeaveChannelMessage): boolean { + return !!(message && message.channel && message.member); + } + + async process(message: LeaveChannelMessage, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing leave channel message for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + if (Channel.isDirectChannel(message.channel)) { + logger.info( + `${this.name} - Channel is direct, do not clean resources for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + return; + } + + await Promise.all([this.removeBadges(message, context), this.removePreferences(message)]); + } + + async removeBadges(message: LeaveChannelMessage, context: ExecutionContext): Promise { + logger.info( + `${this.name} - Removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + try { + const badgeEntity = new UserNotificationBadge(); + assign(badgeEntity, { + workspace_id: message.channel.workspace_id, + company_id: message.channel.company_id, + channel_id: message.channel.id, + user_id: message.member.user_id, + }); + const removedBadges = await gr.services.notifications.badges.removeUserChannelBadges( + badgeEntity, + context, + ); + + logger.info( + `${this.name} - Removed ${removedBadges} badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.warn( + { err }, + `${this.name} - Error while removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } + } + + async removePreferences(message: LeaveChannelMessage): Promise { + if (isDirectChannel(message.channel)) { + logger.info( + `${this.name} - Notification preference was kept for user ${message.member.user_id} in direct channel ${message.channel.id}`, + ); + return; + } + + try { + const preference = merge(new ChannelMemberNotificationPreference(), { + channel_id: message.member.channel_id, + company_id: message.member.company_id, + user_id: message.member.user_id, + }); + + await gr.services.notifications.channelPreferences.delete(preference); + + logger.info( + `${this.name} - Notification preference has been deleted for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.warn( + { err }, + `${this.name} - Error while removing preferences for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted/index.ts deleted file mode 100644 index eb8bd95087..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-deleted/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { assign, merge } from "lodash"; -import { ChannelMemberNotificationPreference, UserNotificationBadge } from "../../../../entities"; -import { logger } from "../../../../../../core/platform/framework"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { Channel, ChannelMember } from "../../../../../channels/entities"; -import { isDirectChannel } from "../../../../../channels/utils"; - -type LeaveChannelMessage = { channel: Channel; member: ChannelMember }; - -export class LeaveChannelMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "channel:member:deleted", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "LeaveChannelMessageProcessor"; - - validate(message: LeaveChannelMessage): boolean { - return !!(message && message.channel && message.member); - } - - async process(message: LeaveChannelMessage): Promise { - logger.info( - `${this.name} - Processing leave channel message for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - if (Channel.isDirectChannel(message.channel)) { - logger.info( - `${this.name} - Channel is direct, do not clean resources for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - return; - } - - await Promise.all([this.removeBadges(message), this.removePreferences(message)]); - } - - async removeBadges(message: LeaveChannelMessage): Promise { - logger.info( - `${this.name} - Removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - try { - const badgeEntity = new UserNotificationBadge(); - assign(badgeEntity, { - workspace_id: message.channel.workspace_id, - company_id: message.channel.company_id, - channel_id: message.channel.id, - user_id: message.member.user_id, - }); - const removedBadges = await this.service.badges.removeUserChannelBadges(badgeEntity); - - logger.info( - `${this.name} - Removed ${removedBadges} badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.warn( - { err }, - `${this.name} - Error while removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } - } - - async removePreferences(message: LeaveChannelMessage): Promise { - if (isDirectChannel(message.channel)) { - logger.info( - `${this.name} - Notification preference was kept for user ${message.member.user_id} in direct channel ${message.channel.id}`, - ); - return; - } - - try { - const preference = merge(new ChannelMemberNotificationPreference(), { - channel_id: message.member.channel_id, - company_id: message.member.company_id, - user_id: message.member.user_id, - }); - - await this.service.channelPreferences.delete(preference); - - logger.info( - `${this.name} - Notification preference has been deleted for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.warn( - { err }, - `${this.name} - Error while removing preferences for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated.ts new file mode 100644 index 0000000000..69904e15dd --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated.ts @@ -0,0 +1,55 @@ +import { merge } from "lodash"; +import { ChannelMemberNotificationPreference } from "../../../entities"; +import { logger } from "../../../../../core/platform/framework"; +import { Channel, ChannelMember } from "../../../../channels/entities"; +import gr from "../../../../global-resolver"; +import { NotificationMessageQueueHandler } from "../../../types"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +type UpdateChannelMessage = { channel: Channel; member: ChannelMember }; + +export class UpdateChannelMemberMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "channel:member:updated", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "UpdateChannelMemberMessageProcessor"; + + validate(message: UpdateChannelMessage): boolean { + return !!(message && message.channel && message.member); + } + + async process(message: UpdateChannelMessage, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing update channel member message for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + const preference = merge(new ChannelMemberNotificationPreference(), { + channel_id: message.member.channel_id, + company_id: message.member.company_id, + user_id: message.member.user_id, + last_read: message.member.last_access || 0, + preferences: message.member.notification_level, + }); + + try { + await gr.services.notifications.channelPreferences.save(preference, context); + + logger.info( + `${this.name} - Channel member notification preference has been updated for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while updating channel member notification preference for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated/index.ts deleted file mode 100644 index a00988b15a..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/channel-member-updated/index.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { merge } from "lodash"; -import { ChannelMemberNotificationPreference } from "../../../../entities"; -import { logger } from "../../../../../../core/platform/framework"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { Channel, ChannelMember } from "../../../../../channels/entities"; - -type UpdateChannelMessage = { channel: Channel; member: ChannelMember }; - -export class UpdateChannelMemberMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "channel:member:updated", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "UpdateChannelMemberMessageProcessor"; - - validate(message: UpdateChannelMessage): boolean { - return !!(message && message.channel && message.member); - } - - async process(message: UpdateChannelMessage): Promise { - logger.info( - `${this.name} - Processing update channel member message for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - const preference = merge(new ChannelMemberNotificationPreference(), { - channel_id: message.member.channel_id, - company_id: message.member.company_id, - user_id: message.member.user_id, - last_read: message.member.last_access || 0, - preferences: message.member.notification_level, - }); - - try { - await this.service.channelPreferences.save(preference); - - logger.info( - `${this.name} - Channel member notification preference has been updated for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while updating channel member notification preference for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read.ts new file mode 100644 index 0000000000..46d7e27fad --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read.ts @@ -0,0 +1,70 @@ +import _ from "lodash"; +import { UserNotificationBadge } from "../../../entities"; +import { logger } from "../../../../../core/platform/framework"; +import { ChannelReadMessage, NotificationMessageQueueHandler } from "../../../types"; +import gr from "../../../../global-resolver"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +export class MarkChannelAsReadMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "channel:read", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "MarkChannelAsReadMessageProcessor"; + + validate(message: ChannelReadMessage): boolean { + return !!( + message && + message.channel && + message.channel.workspace_id && + message.channel.company_id && + message.channel.id && + message.member && + message.member.user_id + ); + } + + async process(message: ChannelReadMessage, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing message for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + await this.removeBadges(message, context); + } + + async removeBadges(message: ChannelReadMessage, context: ExecutionContext): Promise { + logger.info( + `${this.name} - Removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + try { + const badgeEntity = new UserNotificationBadge(); + _.assign(badgeEntity, { + workspace_id: message.channel.workspace_id, + company_id: message.channel.company_id, + channel_id: message.channel.id, + user_id: message.member.user_id, + }); + const removedBadges = await gr.services.notifications.badges.removeUserChannelBadges( + badgeEntity, + context, + ); + + logger.info( + `${this.name} - Removed ${removedBadges} badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.warn( + { err }, + `${this.name} - Error while removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read/index.ts deleted file mode 100644 index 5a20456d7c..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-read/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import _ from "lodash"; -import { UserNotificationBadge } from "../../../../entities"; -import { logger } from "../../../../../../core/platform/framework"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { ChannelReadMessage } from "../../../../types"; - -export class MarkChannelAsReadMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "channel:read", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "MarkChannelAsReadMessageProcessor"; - - validate(message: ChannelReadMessage): boolean { - return !!( - message && - message.channel && - message.channel.workspace_id && - message.channel.company_id && - message.channel.id && - message.member && - message.member.user_id - ); - } - - async process(message: ChannelReadMessage): Promise { - logger.info( - `${this.name} - Processing message for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - await this.removeBadges(message); - } - - async removeBadges(message: ChannelReadMessage): Promise { - logger.info( - `${this.name} - Removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - try { - const badgeEntity = new UserNotificationBadge(); - _.assign(badgeEntity, { - workspace_id: message.channel.workspace_id, - company_id: message.channel.company_id, - channel_id: message.channel.id, - user_id: message.member.user_id, - }); - const removedBadges = await this.service.badges.removeUserChannelBadges(badgeEntity); - - logger.info( - `${this.name} - Removed ${removedBadges} badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.warn( - { err }, - `${this.name} - Error while removing badges for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread.ts new file mode 100644 index 0000000000..bb83b1e92e --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread.ts @@ -0,0 +1,68 @@ +import _ from "lodash"; +import { UserNotificationBadge } from "../../../entities"; +import { logger } from "../../../../../core/platform/framework"; +import { ChannelUnreadMessage, NotificationMessageQueueHandler } from "../../../types"; +import gr from "../../../../global-resolver"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +export class MarkChannelAsUnreadMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "channel:unread", + }; + + readonly options = { + unique: true, + ack: true, + }; + + readonly name = "MarkChannelAsUnreadMessageProcessor"; + + validate(message: ChannelUnreadMessage): boolean { + return !!( + message && + message.channel && + message.channel.workspace_id && + message.channel.company_id && + message.channel.id && + message.member && + message.member.user_id + ); + } + + async process(message: ChannelUnreadMessage, context?: ExecutionContext): Promise { + logger.info( + `${this.name} - Processing message for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + await this.addBadge(message, context); + } + + async addBadge(message: ChannelUnreadMessage, context: ExecutionContext): Promise { + logger.info( + `${this.name} - Creating a badge for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + + try { + const badgeEntity = new UserNotificationBadge(); + _.assign(badgeEntity, { + workspace_id: message.channel.workspace_id, + company_id: message.channel.company_id, + channel_id: message.channel.id, + user_id: message.member.user_id, + mention_type: "unread", + }); + gr.services.notifications.badges.save(badgeEntity, context); + + logger.info( + `${this.name} - Created new badge for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } catch (err) { + logger.warn( + { err }, + `${this.name} - Error while creating new badge for user ${message.member.user_id} in channel ${message.channel.id}`, + ); + } + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread/index.ts deleted file mode 100644 index 082d168412..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/mark-channel-as-unread/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import _ from "lodash"; -import { UserNotificationBadge } from "../../../../entities"; -import { logger } from "../../../../../../core/platform/framework"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { ChannelUnreadMessage } from "../../../../types"; - -export class MarkChannelAsUnreadMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "channel:unread", - }; - - readonly options = { - unique: true, - ack: true, - }; - - readonly name = "MarkChannelAsUnreadMessageProcessor"; - - validate(message: ChannelUnreadMessage): boolean { - return !!( - message && - message.channel && - message.channel.workspace_id && - message.channel.company_id && - message.channel.id && - message.member && - message.member.user_id - ); - } - - async process(message: ChannelUnreadMessage): Promise { - logger.info( - `${this.name} - Processing message for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - await this.addBadge(message); - } - - async addBadge(message: ChannelUnreadMessage): Promise { - logger.info( - `${this.name} - Creating a badge for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - - try { - const badgeEntity = new UserNotificationBadge(); - _.assign(badgeEntity, { - workspace_id: message.channel.workspace_id, - company_id: message.channel.company_id, - channel_id: message.channel.id, - user_id: message.member.user_id, - }); - this.service.badges.save(badgeEntity); - - logger.info( - `${this.name} - Created new badge for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } catch (err) { - logger.warn( - { err }, - `${this.name} - Error while creating new badge for user ${message.member.user_id} in channel ${message.channel.id}`, - ); - } - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications.ts new file mode 100644 index 0000000000..5ba22d5820 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications.ts @@ -0,0 +1,48 @@ +import { logger } from "../../../../../core/platform/framework"; +import { + NotificationMessageQueueHandler, + PushNotificationMessage, + PushNotificationMessageResult, +} from "../../../types"; +import gr from "../../../../global-resolver"; + +/** + * Push new message notification to a set of users + */ +export class PushNotificationMessageProcessor + implements + NotificationMessageQueueHandler +{ + readonly topics = { + in: "notification:push:mobile", + }; + + readonly options = { + unique: true, + ack: true, + }; + + name = "PushMobileNotificationProcessor"; + + validate(message: PushNotificationMessage): boolean { + return !!( + message && + message.channel_id && + message.company_id && + message.workspace_id && + message.message_id && + message.badge_value && + message.user + ); + } + + async process(message: PushNotificationMessage): Promise { + logger.info( + `${this.name} - Processing mobile push notification for channel ${message.channel_id}`, + ); + + await gr.services.notifications.mobilePush.push(message); + + return message; + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications/index.ts deleted file mode 100644 index 4249b4410c..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/mobile-push-notifications/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { logger } from "../../../../../../core/platform/framework"; -import { PushNotificationMessage, PushNotificationMessageResult } from "../../../../types"; -import _ from "lodash"; - -/** - * Push new message notification to a set of users - */ -export class PushNotificationMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "notification:push:mobile", - }; - - readonly options = { - unique: true, - ack: true, - }; - - name = "PushMobileNotificationProcessor"; - - validate(message: PushNotificationMessage): boolean { - return !!( - message && - message.channel_id && - message.company_id && - message.workspace_id && - message.message_id && - message.badge_value && - message.user - ); - } - - async process(message: PushNotificationMessage): Promise { - logger.info( - `${this.name} - Processing mobile push notification for channel ${message.channel_id}`, - ); - - await this.service.mobilePush.push(message); - - return message; - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message.ts b/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message.ts new file mode 100644 index 0000000000..175bdff15e --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message.ts @@ -0,0 +1,259 @@ +import { isDirectChannel } from "../../../../channels/utils"; +import { logger } from "../../../../../core/platform/framework"; +import { MessageNotification } from "../../../../messages/types"; +import { + ChannelMemberNotificationPreference, + ChannelThreadUsers, + getChannelThreadUsersInstance, +} from "../../../entities"; +import { ChannelMemberNotificationLevel } from "../../../../channels/types"; +import { MentionNotification, NotificationMessageQueueHandler } from "../../../types"; +import { ChannelType } from "../../../../../utils/types"; +import gr from "../../../../global-resolver"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +export class NewChannelMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "message:created", + out: "notification:mentions", + }; + + readonly options = { + unique: true, + ack: true, + queue: "message:created:consumer2", + }; + + readonly name = "NewChannelMessageProcessor"; + + validate(message: MessageNotification): boolean { + return !!( + message && + message.channel_id && + message.company_id && + message.workspace_id && + message.creation_date > Date.now() - 5 * 60 * 1000 + ); + } + + async process(message: MessageNotification): Promise { + logger.info( + `${this.name} - Processing notification for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, + ); + logger.debug(`${this.name} - Notification message ${JSON.stringify(message)}`); + + try { + if (message.workspace_id === ChannelType.DIRECT) { + //Fixme: Monkey fix until we find a way to add user to channel BEFORE to add the badge to this channel + await new Promise(r => setTimeout(r, 1000)); + } + + const usersToNotify = await this.getUsersToNotify(message); + + if (!usersToNotify?.length) { + logger.info( + `${this.name} - No users to notify for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, + ); + return; + } + + logger.info( + `${this.name} - Users to notify for message ${message.thread_id}/${message.id} in channel ${ + message.channel_id + } : ['${usersToNotify.join("', '")}']`, + ); + + //Fixme Add user full names if known, need to import microservice + const users_names = {}; + //Fixme add channel full names, need to import microservice + const channels_names = {}; + + return { + channel_id: message.channel_id, + company_id: message.company_id, + message_id: message.id, + thread_id: message.thread_id, + workspace_id: message.workspace_id, + creation_date: message.creation_date, + mentions: { + users: usersToNotify || [], + }, + object_names: { + users: users_names, + channels: channels_names, + }, + + //Temp: should not be used like this when migrating messages to node + //But we don't remember why, so keeping this like this as it works well + text: message.text, + title: message.title, + } as MentionNotification; + } catch (err) { + logger.error( + { err }, + `${this.name} - Error while gettings users to notify for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, + ); + } + } + + async getUsersToNotify( + message: MessageNotification, + context?: ExecutionContext, + ): Promise { + let channelPreferencesForUsers: ChannelMemberNotificationPreference[]; + const threadId = message.thread_id || message.id; + const isNewThread = !message.thread_id || `${message.thread_id}` === `${message.id}`; + const isDirect = isDirectChannel({ workspace_id: message.workspace_id }); + const isAllOrHereMention = this.isAllOrHereMention(message); + + const users: ChannelThreadUsers[] = [ + // message sender is a user in the thread + ...[ + getChannelThreadUsersInstance({ + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: threadId, + user_id: message.sender, + }), + ], + + // mentionned users are users in the thread + ...(message?.mentions?.users?.length + ? message.mentions.users.map(user_id => + getChannelThreadUsersInstance({ + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: threadId, + user_id, + }), + ) + : []), + ]; + + await gr.services.notifications.channelThreads.bulkSave(users, context); + + if (isNewThread || isDirect || isAllOrHereMention) { + //get the channel level preferences + channelPreferencesForUsers = ( + await gr.services.notifications.channelPreferences.getChannelPreferencesForUsers({ + company_id: message.company_id, + channel_id: message.channel_id, + }) + ).getEntities(); + + return this.filterMembersToNotify(message, channelPreferencesForUsers).map(m => m.user_id); + } + + // get the preferences of the users involved in the thread + channelPreferencesForUsers = await this.getAllInvolvedUsersPreferences( + { + channel_id: message.channel_id, + company_id: message.company_id, + thread_id: threadId, + }, + context, + ); + + return this.filterThreadMembersToNotify(message, channelPreferencesForUsers).map( + m => m.user_id, + ); + } + + protected filterMembersToNotify( + message: MessageNotification, + membersPreferences: ChannelMemberNotificationPreference[], + ): ChannelMemberNotificationPreference[] { + logger.debug(`${this.name} - Filter members ${JSON.stringify(membersPreferences)}`); + const isAllOrHere = this.isAllOrHereMention(message); + const isDirect = isDirectChannel({ workspace_id: message.workspace_id }); + return ( + membersPreferences + // 1. Remove the ones which does not want any notification (preference === NONE) + .filter(preference => preference.preferences !== ChannelMemberNotificationLevel.NONE) + // 2. Remove the sender + .filter(preference => String(preference.user_id) !== String(message.sender)) + // 3. Filter based on truth table based on user preferences and current message + .filter(memberPreference => { + const userIsMentionned = this.userIsMentionned(memberPreference.user_id, message); + + const truthTable = [ + isDirect, + // all + memberPreference.preferences === ChannelMemberNotificationLevel.ALL, + // mentions + memberPreference.preferences === ChannelMemberNotificationLevel.MENTIONS && + (isAllOrHere || userIsMentionned), + // me + memberPreference.preferences === ChannelMemberNotificationLevel.ME && userIsMentionned, + ]; + + logger.debug( + `${this.name} - ${ + memberPreference.user_id + } truth table [direct, all, mentions, me] : ${JSON.stringify(truthTable)}`, + ); + + return truthTable.includes(true); + }) + ); + } + + protected filterThreadMembersToNotify( + message: MessageNotification, + membersPreferences: ChannelMemberNotificationPreference[], + ): ChannelMemberNotificationPreference[] { + logger.debug(`${this.name} - Filter thread members ${JSON.stringify(membersPreferences)}`); + return ( + membersPreferences + // 1. Remove the ones which does not want any notification (preference === NONE) + .filter(preference => preference.preferences !== ChannelMemberNotificationLevel.NONE) + //2. Remove the sender + .filter(preference => String(preference.user_id) !== String(message.sender)) + ); + } + + /** + * When message is a response in a thread, get all the users involved in the thread + * ie the ones who where initially mentionned, mentionned in children messages, and the ones who replied + */ + protected async getAllInvolvedUsersPreferences( + thread: { + company_id: string; + channel_id: string; + thread_id: string; + }, + context: ExecutionContext, + ): Promise { + const usersIds: string[] = ( + await gr.services.notifications.channelThreads.getUsersInThread(thread, context) + ) + .getEntities() + .map(thread => thread.user_id); + + return ( + await gr.services.notifications.channelPreferences.getChannelPreferencesForUsers( + { company_id: thread.company_id, channel_id: thread.channel_id }, + usersIds, + undefined, + context, + ) + ).getEntities(); + } + + private isAllOrHereMention(message: MessageNotification): boolean { + return ( + message.mentions && + message.mentions.specials && + (message.mentions.specials.includes("all") || + message.mentions.specials.includes("here") || + message.mentions.specials.includes("channel") || + message.mentions.specials.includes("everyone")) + ); + } + + private userIsMentionned(user: string, message: MessageNotification) { + return message?.mentions?.users?.includes(String(user)); + } +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message/index.ts deleted file mode 100644 index c77e3d83a7..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/new-channel-message/index.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { isDirectChannel } from "../../../../../channels/utils"; -import { logger } from "../../../../../../core/platform/framework"; -import { MessageNotification } from "../../../../../messages/types"; -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { - ChannelMemberNotificationPreference, - ChannelThreadUsers, - getChannelThreadUsersInstance, -} from "../../../../entities"; -import { ChannelMemberNotificationLevel } from "../../../../../channels/types"; -import { MentionNotification } from "../../../../types"; -import { localEventBus } from "../../../../../../core/platform/framework/pubsub"; -import { ChannelType, ResourceEventsPayload } from "../../../../../../utils/types"; - -export class NewChannelMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI) {} - - readonly topics = { - in: "message:created", - out: "notification:mentions", - }; - - readonly options = { - unique: true, - ack: true, - queue: "message:created:consumer2", - }; - - readonly name = "NewChannelMessageProcessor"; - - validate(message: MessageNotification): boolean { - return !!( - message && - message.channel_id && - message.company_id && - message.workspace_id && - message.creation_date > Date.now() - 5 * 60 * 1000 - ); - } - - async process(message: MessageNotification): Promise { - logger.info( - `${this.name} - Processing notification for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, - ); - logger.debug(`${this.name} - Notification message ${JSON.stringify(message)}`); - - try { - if (message.workspace_id === ChannelType.DIRECT) { - //Fixme: Monkey fix until we find a way to add user to channel BEFORE to add the badge to this channel - await new Promise(r => setTimeout(r, 1000)); - } - - const usersToNotify = await this.getUsersToNotify(message); - - if (!usersToNotify?.length) { - logger.info( - `${this.name} - No users to notify for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, - ); - return; - } - - logger.info( - `${this.name} - Users to notify for message ${message.thread_id}/${message.id} in channel ${ - message.channel_id - } : ['${usersToNotify.join("', '")}']`, - ); - - //Fixme Add user full names if known, need to import microservice - const users_names = {}; - //Fixme add channel full names, need to import microservice - const channels_names = {}; - - return { - channel_id: message.channel_id, - company_id: message.company_id, - message_id: message.id, - thread_id: message.thread_id, - workspace_id: message.workspace_id, - creation_date: message.creation_date, - mentions: { - users: usersToNotify || [], - }, - object_names: { - users: users_names, - channels: channels_names, - }, - - //Temp: should not be used like this when migrating messages to node - text: message.text, - title: message.title, - } as MentionNotification; - } catch (err) { - logger.error( - { err }, - `${this.name} - Error while gettings users to notify for message ${message.thread_id}/${message.id} in channel ${message.channel_id}`, - ); - } - } - - async getUsersToNotify(message: MessageNotification): Promise { - let channelPreferencesForUsers: ChannelMemberNotificationPreference[]; - const threadId = message.thread_id || message.id; - const isNewThread = !message.thread_id || `${message.thread_id}` === `${message.id}`; - const isDirect = isDirectChannel({ workspace_id: message.workspace_id }); - const isAllOrHereMention = this.isAllOrHereMention(message); - - const users: ChannelThreadUsers[] = [ - // message sender is a user in the thread - ...[ - getChannelThreadUsersInstance({ - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: threadId, - user_id: message.sender, - }), - ], - - // mentionned users are users in the thread - ...(message?.mentions?.users?.length - ? message.mentions.users.map(user_id => - getChannelThreadUsersInstance({ - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: threadId, - user_id, - }), - ) - : []), - ]; - - await this.service.channelThreads.bulkSave(users); - - if (isNewThread || isDirect || isAllOrHereMention) { - //get the channel level preferences - channelPreferencesForUsers = ( - await this.service.channelPreferences.getChannelPreferencesForUsers({ - company_id: message.company_id, - channel_id: message.channel_id, - }) - ).getEntities(); - - return this.filterMembersToNotify(message, channelPreferencesForUsers).map(m => m.user_id); - } - - // get the preferences of the users involved in the thread - channelPreferencesForUsers = await this.getAllInvolvedUsersPreferences({ - channel_id: message.channel_id, - company_id: message.company_id, - thread_id: threadId, - }); - - return this.filterThreadMembersToNotify(message, channelPreferencesForUsers).map( - m => m.user_id, - ); - } - - protected filterMembersToNotify( - message: MessageNotification, - membersPreferences: ChannelMemberNotificationPreference[], - ): ChannelMemberNotificationPreference[] { - logger.debug(`${this.name} - Filter members ${JSON.stringify(membersPreferences)}`); - const isAllOrHere = this.isAllOrHereMention(message); - const isDirect = isDirectChannel({ workspace_id: message.workspace_id }); - return ( - membersPreferences - // 1. Remove the ones which does not want any notification (preference === NONE) - .filter(preference => preference.preferences !== ChannelMemberNotificationLevel.NONE) - // 2. Remove the sender - .filter(preference => String(preference.user_id) !== String(message.sender)) - // 3. Filter based on truth table based on user preferences and current message - .filter(memberPreference => { - const userIsMentionned = this.userIsMentionned(memberPreference.user_id, message); - - const truthTable = [ - isDirect, - // all - memberPreference.preferences === ChannelMemberNotificationLevel.ALL, - // mentions - memberPreference.preferences === ChannelMemberNotificationLevel.MENTIONS && - (isAllOrHere || userIsMentionned), - // me - memberPreference.preferences === ChannelMemberNotificationLevel.ME && userIsMentionned, - ]; - - logger.debug( - `${this.name} - ${ - memberPreference.user_id - } truth table [direct, all, mentions, me] : ${JSON.stringify(truthTable)}`, - ); - - return truthTable.includes(true); - }) - ); - } - - protected filterThreadMembersToNotify( - message: MessageNotification, - membersPreferences: ChannelMemberNotificationPreference[], - ): ChannelMemberNotificationPreference[] { - logger.debug(`${this.name} - Filter thread members ${JSON.stringify(membersPreferences)}`); - return ( - membersPreferences - // 1. Remove the ones which does not want any notification (preference === NONE) - .filter(preference => preference.preferences !== ChannelMemberNotificationLevel.NONE) - //2. Remove the sender - .filter(preference => String(preference.user_id) !== String(message.sender)) - ); - } - - /** - * When message is a response in a thread, get all the users involved in the thread - * ie the ones who where initially mentionned, mentionned in children messages, and the ones who replied - */ - protected async getAllInvolvedUsersPreferences(thread: { - company_id: string; - channel_id: string; - thread_id: string; - }): Promise { - const usersIds: string[] = (await this.service.channelThreads.getUsersInThread(thread)) - .getEntities() - .map(thread => thread.user_id); - - return ( - await this.service.channelPreferences.getChannelPreferencesForUsers( - { company_id: thread.company_id, channel_id: thread.channel_id }, - usersIds, - ) - ).getEntities(); - } - - private isAllOrHereMention(message: MessageNotification): boolean { - return ( - message.mentions && - message.mentions.specials && - (message.mentions.specials.includes("all") || - message.mentions.specials.includes("here") || - message.mentions.specials.includes("channel") || - message.mentions.specials.includes("everyone")) - ); - } - - private userIsMentionned(user: string, message: MessageNotification) { - return message?.mentions?.users?.includes(String(user)); - } -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users.ts b/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users.ts new file mode 100644 index 0000000000..44e1445fe1 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users.ts @@ -0,0 +1,219 @@ +import { logger } from "../../../../../core/platform/framework"; +import { MobilePushNotifier } from "../../../notifiers"; +import { + MentionNotification, + MentionNotificationResult, + NotificationMessageQueueHandler, + PushNotificationMessage, +} from "../../../types"; +import { ChannelMemberNotificationPreference } from "../../../entities"; +import { UserNotificationBadge } from "../../../entities"; +import _ from "lodash"; +import { websocketEventBus } from "../../../../../core/platform/services/realtime/bus"; +import { + RealtimeEntityActionType, + ResourcePath, +} from "../../../../../core/platform/services/realtime/types"; +import { getNotificationRoomName } from "../../realtime"; +import gr from "../../../../global-resolver"; +import { ExecutionContext } from "../../../../../core/platform/framework/api/crud-service"; + +/** + * Push new message notification to a set of users + */ +export class PushNotificationToUsersMessageProcessor + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "notification:mentions", + }; + + readonly options = { + unique: true, + ack: true, + }; + + name = "PushNotificationToUsersMessageProcessor"; + + validate(message: MentionNotification): boolean { + return !!( + message && + message.channel_id && + message.company_id && + message.workspace_id && + message.creation_date + ); + } + + async process( + message: MentionNotification, + context?: ExecutionContext, + ): Promise { + logger.info(`${this.name} - Processing mention notification for channel ${message.channel_id}`); + + if ( + !message.company_id || + !message.workspace_id || + !message.channel_id || + !message.creation_date + ) { + throw new Error("Missing required fields"); + } + + if (!message.mentions || !message.mentions.users || !message.mentions.users.length) { + logger.info(`${this.name} - Message does not have any user to mention`); + return; + } + + const usersToUpdate = await this.filterUsersOnLastReadChannelTime( + { channel_id: message.channel_id, company_id: message.company_id }, + message.mentions.users, + message.creation_date, + context, + ); + + if (!usersToUpdate.length) { + logger.info(`${this.name} - There are no users to notify from the last read channel date`); + return; + } + + const badges = await this.addNewMessageBadgesForUsers( + { + channel_id: message.channel_id, + company_id: message.company_id, + workspace_id: message.workspace_id, + thread_id: message.thread_id || message.message_id, + message_id: message.message_id, + }, + usersToUpdate, + message.mentions, + context, + ); + + badges.forEach(badge => { + const badgeLocation = { + company_id: message.company_id, + workspace_id: message.workspace_id, + channel_id: message.channel_id, + user: badge.user_id.toString(), + thread_id: message.thread_id || message.message_id, + message_id: message.message_id, + }; + + websocketEventBus.publish(RealtimeEntityActionType.Event, { + type: "notification:desktop", + room: ResourcePath.get(getNotificationRoomName(badge.user_id)), + entity: { + ...badgeLocation, + title: message.title, + text: formatNotificationMessage(message), + }, + resourcePath: null, + result: null, + }); + + this.sendPushNotification(badge.user_id, { + ...badgeLocation, + badge_value: 1, + title: message.title, + text: formatNotificationMessage(message), + }); + }); + } + + async filterUsersOnLastReadChannelTime( + channel: Pick, + users: string[] = [], + timestamp: number, + context?: ExecutionContext, + ): Promise { + if (!users.length) { + return []; + } + + return ( + await gr.services.notifications.channelPreferences.getChannelPreferencesForUsers( + channel, + users, + { + lessThan: timestamp, + }, + context, + ) + ) + .getEntities() + .map((preference: ChannelMemberNotificationPreference) => preference.user_id); + } + + async addNewMessageBadgesForUsers( + badge: Pick< + UserNotificationBadge, + "channel_id" | "company_id" | "thread_id" | "workspace_id" | "message_id" + >, + users: string[] = [], + mentions: MentionNotification["mentions"], + context: ExecutionContext, + ): Promise> { + logger.info(`${this.name} - Update badge for users ${users.join("/")}`); + + return ( + await Promise.all( + users.map(user => { + const badgeEntity = new UserNotificationBadge(); + _.assign(badgeEntity, { + channel_id: badge.channel_id, + company_id: badge.company_id, + workspace_id: badge.workspace_id, + thread_id: badge.thread_id, + message_id: badge.message_id, + user_id: user, + mention_type: mentions.users.includes(user) + ? "me" + : mentions.specials.length > 0 + ? "global" + : badge.thread_id !== badge.message_id + ? "reply" + : null, + }); + return this.saveBadge(badgeEntity, context); + }), + ) + ).filter(Boolean); + } + + private saveBadge( + badge: UserNotificationBadge, + context: ExecutionContext, + ): Promise { + return gr.services.notifications.badges + .save(badge, context) + .then(result => result.entity) + .catch(err => { + logger.warn({ err }, `${this.name} - A badge has not been saved for user ${badge.user_id}`); + return null; + }); + } + + sendPushNotification(user: string, pushNotification: PushNotificationMessage): void { + MobilePushNotifier.get(gr.platformServices.messageQueue).notify(user, pushNotification); + } +} + +function formatNotificationMessage(message: MentionNotification): string { + let text = message.text; + // Clean the message text to remove @userName:id-id-id + ((text || "").match(/@[^: ]+:([0-f-]{36})/gm) || []).forEach(match => { + const string = (match || "").trim(); + const id = string.split(":").pop(); + const fallback = string.split(":").shift(); + text = text.replace(string, message.object_names?.users[id] || fallback); + }); + // Clean the message text to remove #channelName:id-id-id + ((text || "").match(/#[^: ]+:([0-f-]{36})/gm) || []).forEach(match => { + const string = (match || "").trim(); + const id = string.split(":").pop(); + const fallback = string.split(":").shift(); + text = text.replace(string, message.object_names?.channels[id] || fallback); + }); + return text; +} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users/index.ts b/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users/index.ts deleted file mode 100644 index 7b17295a47..0000000000 --- a/twake/backend/node/src/services/notifications/services/engine/processors/push-to-users/index.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { NotificationPubsubHandler, NotificationServiceAPI } from "../../../../api"; -import { logger } from "../../../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../../../core/platform/services/pubsub/api"; -import { MobilePushNotifier } from "../../../../../notifications/notifiers"; -import { - PushNotificationMessage, - MentionNotification, - MentionNotificationResult, -} from "../../../../types"; -import { ChannelMemberNotificationPreference } from "../../../../../../services/notifications/entities/channel-member-notification-preferences"; -import { UserNotificationBadge } from "../../../../../../services/notifications/entities/user-notification-badges"; -import _ from "lodash"; -import { eventBus } from "../../../../../../core/platform/services/realtime/bus"; -import { - RealtimeEntityActionType, - ResourcePath, -} from "../../../../../../core/platform/services/realtime/types"; -import { getNotificationRoomName } from "../../../realtime"; - -/** - * Push new message notification to a set of users - */ -export class PushNotificationToUsersMessageProcessor - implements NotificationPubsubHandler { - constructor(readonly service: NotificationServiceAPI, private pubsub: PubsubServiceAPI) {} - - readonly topics = { - in: "notification:mentions", - }; - - readonly options = { - unique: true, - ack: true, - }; - - name = "PushNotificationToUsersMessageProcessor"; - - validate(message: MentionNotification): boolean { - return !!( - message && - message.channel_id && - message.company_id && - message.workspace_id && - message.creation_date - ); - } - - async process(message: MentionNotification): Promise { - logger.info(`${this.name} - Processing mention notification for channel ${message.channel_id}`); - - if ( - !message.company_id || - !message.workspace_id || - !message.channel_id || - !message.creation_date - ) { - throw new Error("Missing required fields"); - } - - if (!message.mentions || !message.mentions.users || !message.mentions.users.length) { - logger.info(`${this.name} - Message does not have any user to mention`); - return; - } - - const usersToUpdate = await this.filterUsersOnLastReadChannelTime( - { channel_id: message.channel_id, company_id: message.company_id }, - message.mentions.users, - message.creation_date, - ); - - if (!usersToUpdate.length) { - logger.info(`${this.name} - There are no users to notify from the last read channel date`); - return; - } - - const badges = await this.addNewMessageBadgesForUsers( - { - channel_id: message.channel_id, - company_id: message.company_id, - workspace_id: message.workspace_id, - thread_id: message.thread_id || message.message_id, - message_id: message.message_id, - }, - usersToUpdate, - ); - - badges.forEach(badge => { - const badgeLocation = { - company_id: message.company_id, - workspace_id: message.workspace_id, - channel_id: message.channel_id, - user: badge.user_id.toString(), - thread_id: message.thread_id || message.message_id, - message_id: message.message_id, - }; - - eventBus.publish(RealtimeEntityActionType.Event, { - type: "notification:desktop", - room: ResourcePath.get(getNotificationRoomName(badge.user_id)), - entity: { - ...badgeLocation, - title: message.title, - text: formatNotificationMessage(message), - }, - resourcePath: null, - result: null, - }); - - this.sendPushNotification(badge.user_id, { - ...badgeLocation, - badge_value: 1, - title: message.title, - text: formatNotificationMessage(message), - }); - }); - } - - async filterUsersOnLastReadChannelTime( - channel: Pick, - users: string[] = [], - timestamp: number, - ): Promise { - if (!users.length) { - return []; - } - - return ( - await this.service.channelPreferences.getChannelPreferencesForUsers(channel, users, { - lessThan: timestamp, - }) - ) - .getEntities() - .map((preference: ChannelMemberNotificationPreference) => preference.user_id); - } - - async addNewMessageBadgesForUsers( - badge: Pick< - UserNotificationBadge, - "channel_id" | "company_id" | "thread_id" | "workspace_id" | "message_id" - >, - users: string[] = [], - ): Promise> { - logger.info(`${this.name} - Update badge for users ${users.join("/")}`); - - return ( - await Promise.all( - users.map(user => { - const badgeEntity = new UserNotificationBadge(); - _.assign(badgeEntity, { - channel_id: badge.channel_id, - company_id: badge.company_id, - workspace_id: badge.workspace_id, - thread_id: badge.thread_id, - message_id: badge.message_id, - user_id: user, - }); - return this.saveBadge(badgeEntity); - }), - ) - ).filter(Boolean); - } - - private saveBadge(badge: UserNotificationBadge): Promise { - return this.service.badges - .save(badge) - .then(result => result.entity) - .catch(err => { - logger.warn({ err }, `${this.name} - A badge has not been saved for user ${badge.user_id}`); - return null; - }); - } - - sendPushNotification(user: string, pushNotification: PushNotificationMessage): void { - MobilePushNotifier.get(this.pubsub).notify(user, pushNotification); - } -} - -function formatNotificationMessage(message: MentionNotification): string { - let text = message.text; - // Clean the message text to remove @userName:id-id-id - ((text || "").match(/@[^: ]+:([0-f-]{36})/gm) || []).forEach(match => { - const string = (match || "").trim(); - const id = string.split(":").pop(); - const fallback = string.split(":").shift(); - text = text.replace(string, message.object_names?.users[id] || fallback); - }); - // Clean the message text to remove #channelName:id-id-id - ((text || "").match(/#[^: ]+:([0-f-]{36})/gm) || []).forEach(match => { - const string = (match || "").trim(); - const id = string.split(":").pop(); - const fallback = string.split(":").shift(); - text = text.replace(string, message.object_names?.channels[id] || fallback); - }); - return text; -} diff --git a/twake/backend/node/src/services/notifications/services/engine/processors/reaction-notification.ts b/twake/backend/node/src/services/notifications/services/engine/processors/reaction-notification.ts new file mode 100644 index 0000000000..044cd01d8e --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/engine/processors/reaction-notification.ts @@ -0,0 +1,132 @@ +import { + NotificationMessageQueueHandler, + PushNotificationMessage, + ReactionNotification, +} from "../../../types"; +import { logger } from "../../../../../core/platform/framework"; +import { websocketEventBus } from "../../../../../core/platform/services/realtime/bus"; +import { + RealtimeEntityActionType, + ResourcePath, +} from "../../../../../core/platform/services/realtime/types"; +import { MobilePushNotifier } from "../../../notifiers"; +import gr from "../../../../global-resolver"; +import { getNotificationRoomName } from "../../realtime"; +import { Channel } from "../../../../channels/entities/channel"; +import User from "../../../../user/entities/user"; +export class PushReactionNotification + implements NotificationMessageQueueHandler +{ + readonly topics = { + in: "notification:reaction", + }; + + readonly options = { + unique: true, + ack: true, + }; + + name = "PushReactionToUsersMessageProcessor"; + + validate(message: ReactionNotification): boolean { + return !!( + message && + message.message_id && + message.channel_id && + message.company_id && + message.workspace_id && + message.thread_id && + message.user_id && + message.reaction && + message.creation_date && + message.reaction_user_id + ); + } + + async process(task: ReactionNotification): Promise { + logger.info(`${this.name} - Processing reaction notification for message ${task.message_id}`); + + const location = { + company_id: task.company_id, + workspace_id: task.workspace_id, + channel_id: task.channel_id, + user: task.user_id.toString(), + thread_id: task.thread_id || task.message_id, + message_id: task.message_id, + }; + + const { title, text } = await this.buildNotificationMessageContent(task); + + websocketEventBus.publish(RealtimeEntityActionType.Event, { + type: "notification:desktop", + room: ResourcePath.get(getNotificationRoomName(task.user_id)), + entity: { + ...location, + title, + text, + }, + resourcePath: null, + result: null, + }); + + this.sendPushNotification(task.user_id, { + ...location, + title, + text, + }); + } + + sendPushNotification(user: string, reaction: PushNotificationMessage): void { + MobilePushNotifier.get(gr.platformServices.messageQueue).notify(user, reaction); + } + + async buildNotificationMessageContent( + message: ReactionNotification, + ): Promise<{ title: string; text: string }> { + const { company_id, workspace_id, reaction_user_id, reaction, thread_id } = message; + let title = ""; + + const channel: Channel = await gr.services.channels.channels.get({ + id: message.channel_id, + company_id: company_id, + workspace_id: workspace_id, + }); + + const [company, workspace, user] = await Promise.all([ + gr.services.companies.getCompany({ id: company_id }), + workspace_id === "direct" + ? null + : gr.services.workspaces.get({ + company_id: company_id, + id: workspace_id, + }), + gr.services.users.get({ id: reaction_user_id }), + ]); + + const msg = await gr.services.messages.messages.get({ + thread_id: thread_id, + id: message.message_id, + }); + + const companyName = company?.name || ""; + const workspaceName = workspace_id === "direct" ? "Direct" : workspace?.name || ""; + const userName = this.getUserName(user) || "Twake"; + + if (Channel.isDirectChannel(channel)) { + title = `${userName} in ${companyName}`; + } else { + title = `${channel.name} in ${companyName} • ${workspaceName}`; + } + + return { + title, + text: `${userName}: ${reaction} to ${msg?.text || "your message"}`, + }; + } + + getUserName(user: User): string { + return ( + `${user?.first_name || ""} ${user?.last_name || ""}`.trim() || `@${user?.username_canonical}` + ); + } +} diff --git a/twake/backend/node/src/services/notifications/services/index.ts b/twake/backend/node/src/services/notifications/services/index.ts deleted file mode 100644 index 8c06a76d46..0000000000 --- a/twake/backend/node/src/services/notifications/services/index.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { TwakeContext } from "../../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; -import { - ChannelMemberPreferencesServiceAPI, - ChannelThreadUsersServiceAPI, - NotificationServiceAPI, - UserNotificationBadgeServiceAPI, -} from "../api"; -import { getService as getBadgeService } from "./badges"; -import { getService as getPreferencesService } from "./channel-preferences"; -import { getService as getChannelThreadsService } from "./channel-thread-users"; -import { getService as getNotificationPreferencesService } from "./preferences"; -import { getService as getMobilePushService } from "./mobile-push"; -import { NotificationEngine } from "./engine"; -import { NotificationPreferencesService } from "./preferences/service"; -import UserServiceAPI from "../../../services/user/api"; -import { MobilePushService } from "./mobile-push/service"; -import { PushServiceAPI } from "../../../core/platform/services/push/api"; - -export function getService( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - push: PushServiceAPI, - userService: UserServiceAPI, -): NotificationServiceAPI { - return getServiceInstance(databaseService, pubsub, push, userService); -} - -function getServiceInstance( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - push: PushServiceAPI, - userService: UserServiceAPI, -): NotificationServiceAPI { - return new Service(databaseService, pubsub, push, userService); -} - -class Service implements NotificationServiceAPI { - version: "1"; - badges: UserNotificationBadgeServiceAPI; - channelPreferences: ChannelMemberPreferencesServiceAPI; - engine: NotificationEngine; - channelThreads: ChannelThreadUsersServiceAPI; - notificationPreferences: NotificationPreferencesService; - mobilePush: MobilePushService; - - constructor( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - push: PushServiceAPI, - userService: UserServiceAPI, - ) { - this.badges = getBadgeService(databaseService, userService); - this.channelPreferences = getPreferencesService(databaseService); - this.channelThreads = getChannelThreadsService(databaseService); - this.notificationPreferences = getNotificationPreferencesService(databaseService, userService); - this.mobilePush = getMobilePushService(databaseService, push); - this.engine = new NotificationEngine(this, pubsub); - } - - async init(context: TwakeContext): Promise { - try { - await Promise.all([ - this.badges.init(context), - this.channelPreferences.init(context), - this.channelThreads.init(context), - this.engine.init(), - this.notificationPreferences.init(), - this.mobilePush.init(), - ]); - } catch (err) { - console.error("Error while initializing notification service", err); - } - return this; - } -} diff --git a/twake/backend/node/src/services/notifications/services/mobile-push.ts b/twake/backend/node/src/services/notifications/services/mobile-push.ts new file mode 100644 index 0000000000..9c08810e12 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/mobile-push.ts @@ -0,0 +1,59 @@ +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import { PushNotificationMessage } from "../types"; +import User, { TYPE as UserType } from "../../user/entities/user"; +import { CrudException, ExecutionContext } from "../../../core/platform/framework/api/crud-service"; +import gr from "../../global-resolver"; + +export class MobilePushService { + name: "MobilePushService"; + version: "1"; + userRepository: Repository; + + async init(): Promise { + this.userRepository = await gr.database.getRepository(UserType, User); + return this; + } + + //Fixme: add a bulk system to group requests to fcm + async push(message: PushNotificationMessage, context?: ExecutionContext): Promise { + // Get devices and loop over devices + const userId = message.user; + + const user = await this.userRepository.findOne({ id: userId }, {}, context); + + if (!user) { + throw CrudException.notFound(`User ${userId} not found`); + } + + const notification = { + title: message.title, + body: message.text, + sound: "default", + badge: message.badge_value, + }; + + const options = { + notification_data: { + company_id: message.company_id, + workspace_id: message.workspace_id, + channel_id: message.channel_id, + message_id: message.message_id, + thread_id: message.thread_id, + }, + collapse_key: message.channel_id, + }; + + const { preferences } = await gr.services.notifications.preferences.getMerged( + { user_id: user.id, company_id: message.company_id, workspace_id: message.workspace_id }, + user, + ); + if (preferences.mobile_notifications === "never") { + return; + } + if (preferences.private_message_content) { + notification.body = "[Private]"; + } + + await gr.platformServices.push.push(user.devices, notification, options); + } +} diff --git a/twake/backend/node/src/services/notifications/services/mobile-push/index.ts b/twake/backend/node/src/services/notifications/services/mobile-push/index.ts deleted file mode 100644 index 5435580fa5..0000000000 --- a/twake/backend/node/src/services/notifications/services/mobile-push/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { MobilePushService } from "./service"; -import { PushServiceAPI } from "../../../../core/platform/services/push/api"; - -export function getService( - databaseService: DatabaseServiceAPI, - push: PushServiceAPI, -): MobilePushService { - return new MobilePushService(databaseService, push); -} diff --git a/twake/backend/node/src/services/notifications/services/mobile-push/service.ts b/twake/backend/node/src/services/notifications/services/mobile-push/service.ts deleted file mode 100644 index 6cc207f4ac..0000000000 --- a/twake/backend/node/src/services/notifications/services/mobile-push/service.ts +++ /dev/null @@ -1,51 +0,0 @@ -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { PushNotificationMessage } from "../../types"; -import { PushServiceAPI } from "../../../../core/platform/services/push/api"; -import User, { TYPE as UserType } from "../../../user/entities/user"; -import { CrudExeption } from "../../../../core/platform/framework/api/crud-service"; - -export class MobilePushService { - name: "MobilePushService"; - version: "1"; - userRepository: Repository; - - constructor(private database: DatabaseServiceAPI, private pushService: PushServiceAPI) {} - - async init(): Promise { - this.userRepository = await this.database.getRepository(UserType, User); - return this; - } - - //Fixme: add a bulk system to group requests to fcm - async push(message: PushNotificationMessage): Promise { - // Get devices and loop over devices - const userId = message.user; - - const user = await this.userRepository.findOne({ id: userId }); - - if (!user) { - throw CrudExeption.notFound(`User ${userId} not found`); - } - - const notification = { - title: message.title, - body: message.text, - sound: "default", - badge: message.badge_value, - }; - - const options = { - notification_data: { - company_id: message.company_id, - workspace_id: message.workspace_id, - channel_id: message.channel_id, - message_id: message.message_id, - thread_id: message.thread_id, - }, - collapse_key: message.channel_id, - }; - - await this.pushService.push(user.devices, notification, options); - } -} diff --git a/twake/backend/node/src/services/notifications/services/preferences.ts b/twake/backend/node/src/services/notifications/services/preferences.ts new file mode 100644 index 0000000000..6c61c40061 --- /dev/null +++ b/twake/backend/node/src/services/notifications/services/preferences.ts @@ -0,0 +1,150 @@ +import _ from "lodash"; +import { Initializable, TwakeServiceProvider } from "../../../core/platform/framework"; +import { + CrudException, + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import User, { UserNotificationPreferences } from "../../../services/user/entities/user"; +import gr from "../../global-resolver"; + +type UserNotificationPreferencesPrimaryKey = { + company_id: string; + workspace_id: string; + user_id: string; +}; + +export class NotificationPreferencesService implements TwakeServiceProvider, Initializable { + version: "1"; + repository: Repository; + + async init(): Promise { + return this; + } + + async list(): Promise> { + throw new Error("Not implemented"); + } + + async get( + pk: UserNotificationPreferencesPrimaryKey, + user?: User, + context?: ExecutionContext, + ): Promise { + user = user || (await gr.services.users.get({ id: pk.user_id })); + const notificationPreferences = (user?.preferences?.notifications || []).find(n => { + return n.company_id === pk.company_id && n.workspace_id === pk.workspace_id; + }); + return ( + notificationPreferences || { + company_id: pk.company_id, + workspace_id: pk.workspace_id, + preferences: { + highlight_words: [], + night_break: { + enable: false, + from: 0, + to: 0, + }, + private_message_content: false, + mobile_notifications: "always", + email_notifications_delay: 15, + deactivate_notifications_until: 0, + notification_sound: "default", + }, + } + ); + } + + /** We can define preferences for specifically a workspace or for all a company or all Twake + * This function will ensure we get all with inherit and all + */ + async getMerged( + pk: UserNotificationPreferencesPrimaryKey, + user?: User, + ): Promise { + let preferences = await this.get(pk, user); + if (pk.workspace_id !== "all") + preferences = _.merge(await this.get({ ...pk, workspace_id: "all" }), preferences); + if (pk.company_id !== "all") + preferences = _.merge( + await this.get({ ...pk, workspace_id: "all", company_id: "all" }), + preferences, + ); + return preferences; + } + + async delete( + pk: UserNotificationPreferencesPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const user = await gr.services.users.get({ id: pk.user_id }); + const notificationPreferences = (user?.preferences?.notifications || []).filter(n => { + return n.company_id !== pk.company_id || n.workspace_id !== pk.workspace_id; + }); + + await gr.services.users.setPreferences( + { id: pk.user_id }, + { + notifications: notificationPreferences, + }, + context, + ); + + return new DeleteResult("user_notifications_preference", pk as any, true); + } + + async listPreferences( + workspace_id: string, + company_id: string, + user_id: string, + filter: Pick, + context?: ExecutionContext, + ): Promise> { + if (!workspace_id || !company_id || !user_id) { + throw CrudException.badRequest("workspace_id, company_id and user_id are required"); + } + + const user = await gr.services.users.get({ id: user_id }); + + const notificationPreferences = (user?.preferences?.notifications || []).filter(n => { + return n.company_id === company_id && n.workspace_id === workspace_id; + }); + + return new ListResult("user_notifications_preference", notificationPreferences); + } + + async savePreferences( + singleNotificationPreferences: UserNotificationPreferences, + userId: string, + context: ExecutionContext, + ): Promise> { + const user = await gr.services.users.get({ id: userId }); + + const notificationPreferences = (user?.preferences?.notifications || []).filter(n => { + return ( + n.company_id !== singleNotificationPreferences.company_id || + n.workspace_id !== singleNotificationPreferences.workspace_id + ); + }); + notificationPreferences.push(singleNotificationPreferences); + + await gr.services.users.setPreferences( + { id: userId }, + { + notifications: notificationPreferences, + }, + context, + ); + + return new SaveResult( + "user_notifications_preference", + singleNotificationPreferences, + OperationType.CREATE, + ); + } +} diff --git a/twake/backend/node/src/services/notifications/services/preferences/index.ts b/twake/backend/node/src/services/notifications/services/preferences/index.ts deleted file mode 100644 index 4f7fb00f34..0000000000 --- a/twake/backend/node/src/services/notifications/services/preferences/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -import UserServiceAPI from "../../../../services/user/api"; -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { NotificationPreferencesService } from "./service"; - -export function getService( - databaseService: DatabaseServiceAPI, - userService: UserServiceAPI, -): NotificationPreferencesService { - return new NotificationPreferencesService(databaseService, userService); -} diff --git a/twake/backend/node/src/services/notifications/services/preferences/service.ts b/twake/backend/node/src/services/notifications/services/preferences/service.ts deleted file mode 100644 index 26b0cb357f..0000000000 --- a/twake/backend/node/src/services/notifications/services/preferences/service.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import { UserNotificationPreferencesAPI } from "../../api"; -import { - CrudExeption, - ListResult, - SaveResult, - OperationType, - DeleteResult, -} from "../../../../core/platform/framework/api/crud-service"; -import { - UserNotificationPreferences, - UserNotificationPreferencesType, - UserNotificationPreferencesPrimaryKey, -} from "../../entities"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { pick, assign } from "lodash"; -import UserServiceAPI from "../../../../services/user/api"; - -export class NotificationPreferencesService implements UserNotificationPreferencesAPI { - version: "1"; - repository: Repository; - - constructor(private database: DatabaseServiceAPI, private userService: UserServiceAPI) {} - - async init(): Promise { - this.repository = await this.database.getRepository( - UserNotificationPreferencesType, - UserNotificationPreferences, - ); - - return this; - } - - async list(): Promise> { - throw new Error("Not implemented"); - } - - async get(pk: UserNotificationPreferencesPrimaryKey): Promise { - return await this.repository.findOne(pk); - } - - async delete( - pk: UserNotificationPreferencesPrimaryKey, - ): Promise> { - await this.repository.remove(pk as UserNotificationPreferences); - - return new DeleteResult( - UserNotificationPreferencesType, - pk as UserNotificationPreferences, - true, - ); - } - - async listPreferences( - workspace_id: string, - company_id: string, - user_id: string, - filter: Pick, - ): Promise> { - if (!workspace_id || !company_id || !user_id) { - throw CrudExeption.badRequest("workspace_id, company_id and user_id are required"); - } - - return await this.repository.find({ - workspace_id, - company_id, - user_id, - ...pick(filter, ["user_id"]), - }); - } - - async savePreferences( - notificationPreferences: UserNotificationPreferences, - ): Promise> { - const notificationPreferencesEntity = new UserNotificationPreferences(); - assign(notificationPreferencesEntity, notificationPreferences); - - await this.repository.save(notificationPreferencesEntity); - - return new SaveResult( - UserNotificationPreferencesType, - notificationPreferences, - OperationType.CREATE, - ); - } -} diff --git a/twake/backend/node/src/services/notifications/types.ts b/twake/backend/node/src/services/notifications/types.ts index 4e7f8f6102..dc62345e71 100644 --- a/twake/backend/node/src/services/notifications/types.ts +++ b/twake/backend/node/src/services/notifications/types.ts @@ -1,9 +1,9 @@ import { ExecutionContext } from "../../core/platform/framework/api/crud-service"; import { Channel, ChannelMember } from "../channels/entities"; -import { UserNotificationPreferences } from "./entities"; import { PaginationQueryParameters } from "../channels/web/types"; -import { specialMention } from "../messages/types"; +import { SpecialMention } from "../messages/types"; import { uuid } from "../../utils/types"; +import { MessageQueueHandler } from "../../core/platform/services/message-queue/api"; export type NotificationConfiguration = { push: { @@ -26,7 +26,7 @@ export type MentionNotification = { creation_date: number; mentions?: { users: uuid[]; - specials?: specialMention[]; + specials?: SpecialMention[]; }; object_names?: { users: { [id: string]: string }; @@ -47,17 +47,13 @@ export type PushNotificationMessage = { channel_id: uuid; message_id: uuid; thread_id: uuid; - badge_value: number; + badge_value?: number; user: string; title: string; text: string; }; export type PushNotificationMessageResult = PushNotificationMessage; -export class CreateNotificationPreferencesBody { - resource: Pick; -} - export interface NotificationListQueryParameters extends PaginationQueryParameters { company_id: uuid; workspace_id: uuid | "direct"; @@ -75,3 +71,29 @@ export interface NotificationPreferenceListQueryParameters extends PaginationQue company_id: uuid | "all"; user_id: uuid; } + +export type NotificationMessageQueueHandler = MessageQueueHandler< + InputMessage, + OutputMessage +>; + +export type ReactionNotification = { + company_id: uuid; + workspace_id: uuid | "direct"; + channel_id: uuid; + thread_id: uuid; + message_id: uuid; + creation_date: number; + user_id: string; + reaction: string; + reaction_user_id: string; +}; + +export type ReactionNotificationResult = ReactionNotification; + +export type NotificationAcknowledgeBody = { + thread_id: uuid; + workspace_id: uuid | "direct"; + channel_id: uuid; + message_id: uuid; +}; diff --git a/twake/backend/node/src/services/notifications/web/controllers/notification.ts b/twake/backend/node/src/services/notifications/web/controllers/notification.ts index dc6ee0633f..ca3573abfd 100644 --- a/twake/backend/node/src/services/notifications/web/controllers/notification.ts +++ b/twake/backend/node/src/services/notifications/web/controllers/notification.ts @@ -1,16 +1,18 @@ -import { FastifyRequest } from "fastify"; +import { FastifyReply, FastifyRequest } from "fastify"; import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { NotificationServiceAPI } from "../../api"; -import { NotificationListQueryParameters } from "../../types"; +import { NotificationAcknowledgeBody, NotificationListQueryParameters } from "../../types"; import { ResourceCreateResponse, ResourceDeleteResponse, ResourceGetResponse, ResourceListResponse, } from "../../../../utils/types"; -import { UserNotificationBadge } from "../../entities"; +import { UserNotificationBadge, UserNotificationBadgePrimaryKey } from "../../entities"; import { getWebsocketInformation } from "../../services/realtime"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; +import gr from "../../../global-resolver"; +import { getCompanyExecutionContext } from "../../../messages/web/controllers"; +import { BaseChannelsParameters } from "../../../channels/web/types"; +import { WorkspaceExecutionContext } from "../../../channels/types"; export class NotificationController implements @@ -21,27 +23,31 @@ export class NotificationController ResourceDeleteResponse > { - constructor(protected realtime: RealtimeServiceAPI, protected service: NotificationServiceAPI) {} - async list( request: FastifyRequest<{ Querystring: NotificationListQueryParameters; }>, ): Promise> { + const context = getExecutionContext(request); + let resources: UserNotificationBadge[] = []; - let page_token: string = ""; + let page_token = ""; //Get one badge per company if requested if (request.query.all_companies) { - const list = await this.service.badges.listForUserPerCompanies(request.currentUser.id); + const list = await gr.services.notifications.badges.listForUserPerCompanies( + request.currentUser.id, + context, + ); resources = resources.concat(list.getEntities()); } if (request.query.company_id) { - const list = await this.service.badges.listForUser( + const list = await gr.services.notifications.badges.listForUser( request.query.company_id, request.currentUser.id, { ...request.query }, + context, ); resources = resources.concat(list.getEntities()); page_token = list.page_token; @@ -52,7 +58,7 @@ export class NotificationController resources, }, ...(request.query.websockets && { - websockets: this.realtime.sign( + websockets: gr.platformServices.realtime.sign( [getWebsocketInformation(request.currentUser)], request.currentUser.id, ), @@ -62,4 +68,57 @@ export class NotificationController }), }; } + + /** + * Acknowledge a notification + * + * @param {FastifyRequest} request - The request object + * @param {FastifyReply} reply - The reply object + * @returns {Promise} - The response object + */ + async acknowledge( + request: FastifyRequest<{ + Params: { + company_id: string; + }; + Body: NotificationAcknowledgeBody; + }>, + reply: FastifyReply, + ): Promise { + const context = getExecutionContext(request); + const { company_id } = request.params; + const { workspace_id, channel_id, thread_id, message_id } = request.body; + + try { + await gr.services.notifications.badges.acknowledge( + { + channel_id, + company_id, + thread_id, + user_id: context.user.id, + workspace_id, + message_id, + }, + context, + ); + + return reply.send(true); + } catch (err) { + return reply.send(false); + } + } +} + +function getExecutionContext(request: FastifyRequest): WorkspaceExecutionContext { + return { + user: request.currentUser, + url: request.url, + method: request.routerMethod, + reqId: request.id, + transport: "http", + workspace: { + company_id: undefined, + workspace_id: undefined, + }, + }; } diff --git a/twake/backend/node/src/services/notifications/web/controllers/preferences.ts b/twake/backend/node/src/services/notifications/web/controllers/preferences.ts index 218863b6c4..c4c350446b 100644 --- a/twake/backend/node/src/services/notifications/web/controllers/preferences.ts +++ b/twake/backend/node/src/services/notifications/web/controllers/preferences.ts @@ -1,62 +1,68 @@ -import { FastifyRequest, FastifyReply } from "fastify"; -import { CrudController } from "../../../../core/platform/services/webserver/types"; -import { NotificationServiceAPI } from "../../api"; +import { FastifyReply, FastifyRequest } from "fastify"; +import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; +import { UserNotificationPreferences } from "../../../../services/user/entities/user"; import { handleError } from "../../../../utils/handleError"; -import { - NotificationPreferenceListQueryParameters, - CreateNotificationPreferencesBody, -} from "../../types"; -import { - ResourceCreateResponse, - ResourceDeleteResponse, - ResourceGetResponse, - ResourceListResponse, -} from "../../../../utils/types"; -import { UserNotificationPreferences } from "../../entities"; +import { ResourceCreateResponse, ResourceListResponse } from "../../../../utils/types"; +import gr from "../../../global-resolver"; +import { NotificationPreferenceListQueryParameters } from "../../types"; const ALL = "all"; -export class NotificationPrerencesController - implements - CrudController< - ResourceGetResponse, - ResourceCreateResponse, - ResourceListResponse, - ResourceDeleteResponse - > { - constructor(protected service: NotificationServiceAPI) {} - +export class NotificationPreferencesController { async list( request: FastifyRequest<{ Querystring: NotificationPreferenceListQueryParameters; }>, ): Promise> { - const list = await this.service.notificationPreferences.listPreferences( + const list = await gr.services.notifications.preferences.listPreferences( ALL, ALL, request.currentUser.id, { ...request.query }, ); - return { resources: list.getEntities() }; + let resources = list.getEntities(); + + if (!resources.length) { + resources = [ + { + company_id: ALL, + workspace_id: ALL, + preferences: { + highlight_words: [], + night_break: { enable: false, from: 0, to: 0 }, + private_message_content: false, + mobile_notifications: "always", + email_notifications_delay: 15, + deactivate_notifications_until: 0, + notification_sound: "default", + }, + }, + ]; + } + + return { resources }; } async save( - request: FastifyRequest<{ Body: CreateNotificationPreferencesBody }>, + request: FastifyRequest<{ Body: { resource: UserNotificationPreferences } }>, reply: FastifyReply, + context?: ExecutionContext, ): Promise> { const entity = { - ...request.body.resource, - ...{ - workspace_id: ALL, - company_id: ALL, - user_id: request.currentUser.id, + workspace_id: ALL, + company_id: ALL, + user_id: request.currentUser.id, + preferences: { + ...request.body.resource, }, }; try { - const result = await this.service.notificationPreferences.savePreferences( + const result = await gr.services.notifications.preferences.savePreferences( entity as UserNotificationPreferences, + request.currentUser.id, + context, ); if (result) { diff --git a/twake/backend/node/src/services/notifications/web/index.ts b/twake/backend/node/src/services/notifications/web/index.ts index 4449efd817..cef68280ae 100644 --- a/twake/backend/node/src/services/notifications/web/index.ts +++ b/twake/backend/node/src/services/notifications/web/index.ts @@ -1,14 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import { NotificationServiceAPI } from "../api"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: NotificationServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /internal/services/notifications/v1 routes"); diff --git a/twake/backend/node/src/services/notifications/web/routes.ts b/twake/backend/node/src/services/notifications/web/routes.ts index 72ad55a45b..2749c36717 100644 --- a/twake/backend/node/src/services/notifications/web/routes.ts +++ b/twake/backend/node/src/services/notifications/web/routes.ts @@ -1,18 +1,13 @@ import { FastifyInstance, FastifyPluginCallback } from "fastify"; -import { NotificationController, NotificationPrerencesController } from "./controllers"; -import { NotificationServiceAPI } from "../api"; +import { NotificationController, NotificationPreferencesController } from "./controllers"; import { createNotificationPreferencesSchema } from "./schemas"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; const badgesUrl = "/badges"; const notificationPreferencesUrl = "/preferences"; -const routes: FastifyPluginCallback<{ - service: NotificationServiceAPI; - realtime: RealtimeServiceAPI; -}> = (fastify: FastifyInstance, options, next) => { - const notificationController = new NotificationController(options.realtime, options.service); - const notificationPrerencesController = new NotificationPrerencesController(options.service); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const notificationController = new NotificationController(); + const notificationPreferencesController = new NotificationPreferencesController(); fastify.route({ method: "GET", @@ -25,7 +20,7 @@ const routes: FastifyPluginCallback<{ method: "GET", url: notificationPreferencesUrl, preValidation: [fastify.authenticate], - handler: notificationPrerencesController.list.bind(notificationPrerencesController), + handler: notificationPreferencesController.list.bind(notificationPreferencesController), }); fastify.route({ @@ -33,7 +28,14 @@ const routes: FastifyPluginCallback<{ url: notificationPreferencesUrl, preValidation: [fastify.authenticate], schema: createNotificationPreferencesSchema, - handler: notificationPrerencesController.save.bind(notificationPrerencesController), + handler: notificationPreferencesController.save.bind(notificationPreferencesController), + }); + + fastify.route({ + method: "POST", + url: `${badgesUrl}/:company_id/acknowledge`, + preValidation: [fastify.authenticate], + handler: notificationController.acknowledge.bind(notificationController), }); next(); diff --git a/twake/backend/node/src/services/online/api.ts b/twake/backend/node/src/services/online/api.ts index 3210ddf888..ca78f8ed48 100644 --- a/twake/backend/node/src/services/online/api.ts +++ b/twake/backend/node/src/services/online/api.ts @@ -1,8 +1,13 @@ import { TwakeServiceProvider } from "../../core/platform/framework"; +import UserOnline, { UserOnlinePrimaryKey } from "./entities/user-online"; -export type OnlineTuple = [string, boolean]; +export type OnlineEvent = { + company_id: string; + user_id: string; + is_online: boolean; +}; -export type UsersOnlineMessage = Array; +export type UsersOnlineMessage = Array; export type OnlineGetRequest = { /* Array of ids to get status */ @@ -10,10 +15,11 @@ export type OnlineGetRequest = { }; export type OnlineGetResponse = { - data: UsersOnlineMessage; + data: Array<[string, boolean]>; }; export interface OnlineServiceAPI extends TwakeServiceProvider { isOnline(userId: string): Promise; - setLastSeenOnline(userIds: Array, lastSeen: number): Promise; + setLastSeenOnline(userIds: Array, lastSeen: number, is_connected: boolean): Promise; + get(userId: UserOnlinePrimaryKey): Promise; } diff --git a/twake/backend/node/src/services/online/constants.ts b/twake/backend/node/src/services/online/constants.ts index 37570158d0..f45386007d 100644 --- a/twake/backend/node/src/services/online/constants.ts +++ b/twake/backend/node/src/services/online/constants.ts @@ -1,3 +1,2 @@ -export const JOB_CRON_EXPRESSION = "*/5 * * * * *"; -export const DISCONNECTED_DELAY = 60000; +export const DISCONNECTED_DELAY = 900000; export const ONLINE_TOPIC = "user:online"; diff --git a/twake/backend/node/src/services/online/cron.ts b/twake/backend/node/src/services/online/cron.ts deleted file mode 100644 index 988e8e7d28..0000000000 --- a/twake/backend/node/src/services/online/cron.ts +++ /dev/null @@ -1,41 +0,0 @@ -import WebSocketAPI from "../../core/platform/services/websocket/provider"; -import { getLogger, TwakeLogger } from "../../core/platform/framework/logger"; -import { CronAPI } from "../../core/platform/services/cron/api"; -import { WebSocket } from "../../core/platform/services/websocket/types"; -import { Initializable } from "../../core/platform/framework"; -import { JOB_CRON_EXPRESSION } from "./constants"; -import { filter } from "lodash"; -import { OnlineServiceAPI } from "./api"; - -export default class OnlineJob implements Initializable { - private logger: TwakeLogger; - constructor( - private cron: CronAPI, - private websocket: WebSocketAPI, - private onlineService: OnlineServiceAPI, - ) { - this.logger = getLogger("OnlineJob"); - } - - async init(): Promise { - const task = this.cron.schedule(JOB_CRON_EXPRESSION, async () => { - this.logger.info("Running online job"); - - const connectedWebsockets: WebSocket[] = filter( - this.websocket.getIo().sockets.sockets, - "connected", - ) as unknown as WebSocket[]; - - await this.onlineService.setLastSeenOnline( - connectedWebsockets - .filter(ws => ws?.decoded_token) - .map(ws => this.websocket.getUser(ws)) - .map(user => user.id), - Date.now(), - ); - }); - this.logger.debug("Status Job has been submitted", task.id); - - return this; - } -} diff --git a/twake/backend/node/src/services/online/entities/user-online.ts b/twake/backend/node/src/services/online/entities/user-online.ts index e4f88db52d..9071edbdff 100644 --- a/twake/backend/node/src/services/online/entities/user-online.ts +++ b/twake/backend/node/src/services/online/entities/user-online.ts @@ -13,6 +13,10 @@ export default class UserOnline { @Column("user_id", "timeuuid", { generator: "timeuuid" }) user_id: string; + @Type(() => Boolean) + @Column("is_connected", "boolean") + is_connected: boolean; + /** * Save the date the user has been seen connected */ diff --git a/twake/backend/node/src/services/online/index.ts b/twake/backend/node/src/services/online/index.ts index f137341681..9c9f9f02ed 100644 --- a/twake/backend/node/src/services/online/index.ts +++ b/twake/backend/node/src/services/online/index.ts @@ -1,113 +1,15 @@ -import { PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { CronAPI } from "../../core/platform/services/cron/api"; -import WebSocketAPI from "../../core/platform/services/websocket/provider"; -import Repository from "../../core/platform/services/database/services/orm/repository/repository"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; - -import { OnlineGetRequest, OnlineGetResponse, OnlineServiceAPI } from "./api"; -import OnlineJob from "./cron"; -import { OnlinePubsubService } from "./pubsub"; -import { DISCONNECTED_DELAY } from "./constants"; -import UserOnline, { TYPE as ONLINE_TYPE, getInstance } from "./entities/user-online"; +import { Prefix, TwakeService } from "../../core/platform/framework"; @Prefix("/internal/services/online/v1") -@Consumes(["webserver", "websocket", "cron", "pubsub", "database"]) -export default class OnlineService - extends TwakeService - implements OnlineServiceAPI -{ +export default class OnlineService extends TwakeService { version = "1"; name = "online"; - service: OnlineServiceAPI; - private job: OnlineJob; - private pubsubService: OnlinePubsubService; - onlineRepository: Repository; - api(): OnlineServiceAPI { - return this.service; + api(): undefined { + return undefined; } public async doInit(): Promise { - const websocket = this.context.getProvider("websocket"); - const cron = this.context.getProvider("cron"); - const pubsub = this.context.getProvider("pubsub"); - const database = this.context.getProvider("database"); - - this.onlineRepository = await database.getRepository(ONLINE_TYPE, UserOnline); - - this.pubsubService = new OnlinePubsubService(pubsub); - this.job = new OnlineJob(cron, websocket, this); - - await this.pubsubService.init(); - await this.job.init(); - - websocket.onUserConnected(event => { - this.logger.info("User connected", event.user.id); - // save the last connection date - this.setLastSeenOnline([event.user.id], Date.now()); - // broadcast to global pubsub so that everyone can publish to websockets - this.pubsubService.broadcastOnline([[event.user.id, true]]); - - event.socket.on( - "online:get", - async (request: OnlineGetRequest, ack: (response: OnlineGetResponse) => void) => { - this.logger.debug( - `Got an online:get request for users "[${(request.data || []).join(",")}]"`, - ); - - ack({ data: await this.getOnlineStatuses(request.data) }); - }, - ); - }); - - websocket.onUserDisconnected(event => { - this.logger.info("User disconnected", event.user.id); - // Since the user can be connected on several nodes, we cannot directly set it status to offline - // We do nothing, the cron will do the job... - }); - return this; } - - private async getOnlineStatuses(ids: Array = []): Promise> { - return this.areOnline(ids); - } - - async setLastSeenOnline(userIds: Array = [], date: number): Promise { - this.logger.debug(`setLastSeenOnline ${userIds.join(",")}`); - if (!userIds.length) { - return; - } - const last_seen = date || Date.now(); - const uniqueIds = new Set(userIds); - this.logger.info(`Update last active state for users ${userIds.join(",")}`); - const onlineUsers: UserOnline[] = Array.from(uniqueIds.values()).map(user_id => - getInstance({ user_id, last_seen }), - ); - await this.onlineRepository.saveAll(onlineUsers); - } - - async isOnline(userId: string): Promise { - const user = await this.onlineRepository.findOne({ user_id: userId }); - - if (!user) { - return false; - } - - return Date.now() - user.last_seen < DISCONNECTED_DELAY; - } - - private async areOnline(ids: Array = []): Promise> { - const users = await this.onlineRepository.find({}, { $in: [["user_id", ids]] }); - - return users.getEntities().map(user => [user.user_id, this.isStillConnected(user.last_seen)]); - } - - /** - * let's say that a user is connected when its last connection is more than some delay ago - */ - private isStillConnected(date: number): boolean { - return Date.now() - date < DISCONNECTED_DELAY; - } } diff --git a/twake/backend/node/src/services/online/pubsub/index.ts b/twake/backend/node/src/services/online/pubsub/index.ts index e8425335c5..c0aec93267 100644 --- a/twake/backend/node/src/services/online/pubsub/index.ts +++ b/twake/backend/node/src/services/online/pubsub/index.ts @@ -1,17 +1,18 @@ import { getLogger, Initializable, TwakeLogger } from "../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; +import { MessageQueueServiceAPI } from "../../../core/platform/services/message-queue/api"; import { UsersOnlineMessage } from "../api"; import { ONLINE_TOPIC } from "../constants"; import { UserOnlineProcessor } from "./processor"; +import gr from "../../global-resolver"; export class OnlinePubsubService implements Initializable { private logger: TwakeLogger; - constructor(private pubsub: PubsubServiceAPI) { + constructor() { this.logger = getLogger("online.pubsub.OnlinePubsubService"); } async init(): Promise { - this.pubsub.processor.addHandler(new UserOnlineProcessor()); + gr.platformServices.messageQueue.processor.addHandler(new UserOnlineProcessor()); return this; } @@ -20,9 +21,9 @@ export class OnlinePubsubService implements Initializable { return; } - this.logger.debug(`Publishing online users ${online.map(u => u[0]).join(",")}`); + this.logger.debug(`Publishing online users ${online.map(u => u.user_id).join(",")}`); - return this.pubsub.publish(ONLINE_TOPIC, { + return gr.platformServices.messageQueue.publish(ONLINE_TOPIC, { data: online, }); } diff --git a/twake/backend/node/src/services/online/pubsub/processor.ts b/twake/backend/node/src/services/online/pubsub/processor.ts index d999ea0463..a73e48f9c5 100644 --- a/twake/backend/node/src/services/online/pubsub/processor.ts +++ b/twake/backend/node/src/services/online/pubsub/processor.ts @@ -1,14 +1,15 @@ -import { PubsubHandler } from "../../../core/platform/services/pubsub/api"; +import _ from "lodash"; import { getLogger, TwakeLogger } from "../../../core/platform/framework"; +import { MessageQueueHandler } from "../../../core/platform/services/message-queue/api"; +import { websocketEventBus } from "../../../core/platform/services/realtime/bus"; import { RealtimeEntityActionType, ResourcePath, } from "../../../core/platform/services/realtime/types"; -import { eventBus } from "../../../core/platform/services/realtime/bus"; import { UsersOnlineMessage } from "../api"; import { ONLINE_TOPIC } from "../constants"; -export class UserOnlineProcessor implements PubsubHandler { +export class UserOnlineProcessor implements MessageQueueHandler { private logger: TwakeLogger; readonly topics = { in: ONLINE_TOPIC, @@ -30,16 +31,20 @@ export class UserOnlineProcessor implements PubsubHandler { - this.logger.debug(`Pushing user online status for users ${message.map(u => u[0]).join(",")}`); - - // TODO: We can not push all users to all websockets, we need to categorize them per company and then push them in specific topic per company - - eventBus.publish(RealtimeEntityActionType.Event, { - type: "user:online", - room: ResourcePath.get("/users/online"), - entity: message, - resourcePath: null, - result: null, + this.logger.debug( + `Pushing user online status for users ${message.map(u => u.user_id).join(",")}`, + ); + + const grouped_data = _.groupBy(message, "company_id"); + + Object.values(grouped_data).forEach((messagePerCompany: UsersOnlineMessage) => { + websocketEventBus.publish(RealtimeEntityActionType.Event, { + type: "user:online", + room: ResourcePath.get(`/users/online/${messagePerCompany[0].company_id}`), + entity: { online: messagePerCompany }, + resourcePath: null, + result: null, + }); }); return; diff --git a/twake/backend/node/src/services/online/service/index.ts b/twake/backend/node/src/services/online/service/index.ts new file mode 100644 index 0000000000..6c71bfe554 --- /dev/null +++ b/twake/backend/node/src/services/online/service/index.ts @@ -0,0 +1,169 @@ +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; + +import { OnlineGetRequest, OnlineGetResponse, OnlineServiceAPI } from "../api"; +import { OnlinePubsubService } from "../pubsub"; +import { DISCONNECTED_DELAY } from "../constants"; +import UserOnline, { + getInstance, + TYPE as ONLINE_TYPE, + UserOnlinePrimaryKey, +} from "../entities/user-online"; +import gr from "../../global-resolver"; +import { getLogger, TwakeLogger, TwakeServiceProvider } from "../../../core/platform/framework"; +import { getUserRoom } from "../../../services/user/realtime"; +import User from "../../../services/user/entities/user"; +import { WebsocketUserEvent } from "../../../core/platform/services/websocket/types"; +import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; + +export default class OnlineServiceImpl implements TwakeServiceProvider { + version = "1"; + service: OnlineServiceAPI; + private pubsubService: OnlinePubsubService; + onlineRepository: Repository; + private logger: TwakeLogger; + + constructor() { + this.logger = getLogger("online.service"); + } + + public async init(): Promise { + this.onlineRepository = await gr.database.getRepository(ONLINE_TYPE, UserOnline); + + this.pubsubService = new OnlinePubsubService(); + + await this.pubsubService.init(); + + gr.platformServices.websocket.onUserConnected(async event => { + const user: User = await gr.services.users.get({ + id: event.user.id, + }); + + const companies = user?.cache?.companies; + + this.logger.info("User connected", event.user.id); + // save the last connection date + this.setLastSeenOnline([event.user.id], Date.now(), true); + // broadcast to global pubsub so that everyone can publish to websockets + this.broadcastOnline(event, companies); + + event.socket.on( + "online:get", + async (request: OnlineGetRequest, ack: (response: OnlineGetResponse) => void) => { + this.logger.debug(`Got an online:get request for ${(request.data || []).length} users`); + ack({ data: await this.getOnlineStatuses(request.data) }); + }, + ); + + event.socket.on( + "online:set", + async (request: OnlineGetRequest, ack: () => void): Promise => { + this.logger.debug(`Got an online:set request for ${(request.data || []).length} users`); + + this.broadcastOnline(event, companies); + this.setLastSeenOnline([event.user.id], Date.now(), true); + ack(); + }, + ); + }); + + gr.platformServices.websocket.onUserDisconnected(async event => { + this.logger.info("User disconnected", event.user.id); + // Since the user can be connected on several nodes, we cannot directly set it status to offline + const room = getUserRoom(event.user.id); + const userSockets = await event.socket.in(room).allSockets(); + + if (userSockets.size === 0) { + this.pubsubService.broadcastOnline([ + { + company_id: "toBeFetched", + user_id: event.user.id, + is_online: false, + }, + ]); + this.setLastSeenOnline([event.user.id], Date.now(), false); + } + }); + + return this; + } + + private async getOnlineStatuses(ids: Array): Promise> { + console.log("socket getOnlineStatuses", ids); + return this.areOnline(ids); + } + + async setLastSeenOnline( + userIds: Array = [], + date: number, + is_connected: boolean, + ): Promise { + this.logger.debug(`setLastSeenOnline ${userIds.join(",")}`); + if (!userIds.length) { + return; + } + const last_seen = date || Date.now(); + const uniqueIds = new Set(userIds); + this.logger.info(`Update last active state for users ${userIds.join(",")}`); + const onlineUsers: UserOnline[] = Array.from(uniqueIds.values()).map(user_id => + getInstance({ user_id, last_seen, is_connected }), + ); + await this.onlineRepository.saveAll(onlineUsers); + } + + async isOnline(userId: string, context?: ExecutionContext): Promise { + const user = await this.onlineRepository.findOne({ user_id: userId }, {}, context); + + if (!user) { + return false; + } + + return Date.now() - user.last_seen < DISCONNECTED_DELAY; + } + + private async areOnline( + ids: Array = [], + context?: ExecutionContext, + ): Promise> { + const users = []; + //This foreach is needed for $in operators https://github.com/linagora/Twake/issues/1246 + for (let i = 0; i < ids.length; i += 100) { + users.push( + ...( + await this.onlineRepository.find( + {}, + { $in: [["user_id", ids.slice(i, i + 100)]] }, + context, + ) + ).getEntities(), + ); + } + + return users.map(user => [ + user.user_id, + this.isStillConnected(user.last_seen, user.is_connected), + ]); + } + + /** + * let's say that a user is connected when its last connection is more than some delay ago + */ + private isStillConnected(date: number, is_connected: boolean): boolean { + return Date.now() - date < DISCONNECTED_DELAY && is_connected; + } + + private broadcastOnline(event: WebsocketUserEvent, companies: Array): void { + (companies || []).forEach(company => { + this.pubsubService.broadcastOnline([ + { + company_id: company, + user_id: event.user.id, + is_online: true, + }, + ]); + }); + } + + async get(pk: UserOnlinePrimaryKey): Promise { + return await this.onlineRepository.findOne(pk); + } +} diff --git a/twake/backend/node/src/services/previews/api.ts b/twake/backend/node/src/services/previews/api.ts deleted file mode 100644 index 075445a5df..0000000000 --- a/twake/backend/node/src/services/previews/api.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TwakeServiceProvider, Initializable } from "../../core/platform/framework/api"; -import { PubsubHandler, PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import { PreviewProcessService } from "./services/processing/service"; - -export interface PreviewServiceAPI extends TwakeServiceProvider, Initializable { - pubsub: PubsubServiceAPI; - previewProcess: PreviewProcessService; -} - -/** - * A notification hander is in charge of processing a notification from the pubsub layer and then optionally produces something to be consumed by another handler somewhere in the platform. - */ -export interface PreviewPubsubHandler - extends PubsubHandler { - service: PreviewServiceAPI; -} diff --git a/twake/backend/node/src/services/previews/index.ts b/twake/backend/node/src/services/previews/index.ts index 3c645d3714..222ae33684 100644 --- a/twake/backend/node/src/services/previews/index.ts +++ b/twake/backend/node/src/services/previews/index.ts @@ -1,35 +1,23 @@ import WebServerAPI from "../../core/platform/services/webserver/provider"; -import { TwakeService, Prefix, Consumes } from "../../core/platform/framework"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import StorageAPI from "../../core/platform/services/storage/provider"; -import { PubsubServiceAPI } from "../../core/platform/services/pubsub/api"; -import { PreviewServiceAPI } from "./api"; -import web from "./web/index"; -import { getService } from "./services/index"; +import { Prefix, TwakeService } from "../../core/platform/framework"; +import web from "./web"; @Prefix("/internal/services/previews/v1") -@Consumes(["webserver", "database", "storage", "pubsub"]) -export default class PreviewsService extends TwakeService { +export default class PreviewsService extends TwakeService { version = "1"; name = "previews"; - service: PreviewServiceAPI; - - api(): PreviewServiceAPI { - return this.service; - } public async doInit(): Promise { const fastify = this.context.getProvider("webserver").getServer(); - const database = this.context.getProvider("database"); - const storage = this.context.getProvider("storage"); - const pubsub = this.context.getProvider("pubsub"); - - this.service = getService(database, pubsub, storage); - await this.service.init(); fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service }); + web(instance, { prefix: this.prefix }); next(); }); return this; } + + // TODO: remove + api(): undefined { + return undefined; + } } diff --git a/twake/backend/node/src/services/previews/services/engine/clear.ts b/twake/backend/node/src/services/previews/services/engine/clear.ts deleted file mode 100644 index 013d6a6393..0000000000 --- a/twake/backend/node/src/services/previews/services/engine/clear.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { PreviewPubsubHandler, PreviewServiceAPI } from "../../api"; -import { logger, TwakeContext } from "../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; -import { PreviewPubsubCallback, PreviewClearPubsubRequest } from "../../types"; -import StorageAPI from "../../../../core/platform/services/storage/provider"; - -/** - * Clear thumbnails when the delete task is called - */ -export class ClearProcessor - implements PreviewPubsubHandler -{ - readonly name = "ClearProcessor"; - - readonly topics = { - in: "services:preview:clear", - out: "services:preview:callback", - }; - - readonly options = { - unique: true, - ack: true, - }; - - constructor( - service: PreviewServiceAPI, - private pubsub: PubsubServiceAPI, - readonly storage: StorageAPI, - ) { - this.service = service; - } - service: PreviewServiceAPI; - // eslint-disable-next-line @typescript-eslint/no-unused-vars - init?(context?: TwakeContext): Promise { - throw new Error("Method not implemented."); - } - - validate(message: PreviewClearPubsubRequest): boolean { - return !!(message && message.document); - } - - async process(message: PreviewClearPubsubRequest): Promise { - logger.info(`${this.name} - Processing preview generation ${message.document.id}`); - - if (!this.validate(message)) { - throw new Error("Missing required fields"); - } - - for (let i = 0; i < message.document.thumbnails_number; i++) { - await this.storage.remove(`${message.document.path.replace(/\/$/, "")}/${i}.png`); - } - - return { document: message.document, thumbnails: [] }; - } -} diff --git a/twake/backend/node/src/services/previews/services/engine/index.ts b/twake/backend/node/src/services/previews/services/engine/index.ts deleted file mode 100644 index 30481f8ef1..0000000000 --- a/twake/backend/node/src/services/previews/services/engine/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -import StorageAPI from "../../../../../src/core/platform/services/storage/provider"; -import { Initializable } from "../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; -import { PreviewServiceAPI } from "../../api"; -import { ClearProcessor } from "./clear"; -import { PreviewProcessor } from "./service"; - -/** - * The notification engine is in charge of processing data and delivering user notifications on the right place - */ -export class PreviewEngine implements Initializable { - constructor( - private service: PreviewServiceAPI, - private pubsub: PubsubServiceAPI, - private storage: StorageAPI, - ) {} - - async init(): Promise { - this.pubsub.processor.addHandler(new PreviewProcessor(this.service, this.pubsub, this.storage)); - this.pubsub.processor.addHandler(new ClearProcessor(this.service, this.pubsub, this.storage)); - - return this; - } -} diff --git a/twake/backend/node/src/services/previews/services/engine/service.ts b/twake/backend/node/src/services/previews/services/engine/service.ts deleted file mode 100644 index 5b5c82babf..0000000000 --- a/twake/backend/node/src/services/previews/services/engine/service.ts +++ /dev/null @@ -1,123 +0,0 @@ -import fs from "fs"; -import { promises as fsPromise } from "fs"; -import { PreviewPubsubHandler, PreviewServiceAPI } from "../../api"; -import { logger, TwakeContext } from "../../../../core/platform/framework"; -import { PubsubServiceAPI } from "../../../../core/platform/services/pubsub/api"; -import { PreviewPubsubCallback, PreviewPubsubRequest, ThumbnailResult } from "../../types"; -import { getTmpFile } from "../../utils"; -import StorageAPI from "../../../../core/platform/services/storage/provider"; - -const { unlink } = fsPromise; -/** - * Generate thumbnails when the upload is finished - */ -export class PreviewProcessor - implements PreviewPubsubHandler -{ - readonly name = "PreviewProcessor"; - - constructor( - readonly service: PreviewServiceAPI, - private pubsub: PubsubServiceAPI, - readonly storage: StorageAPI, - ) {} - - init?(context?: TwakeContext): Promise { - throw new Error("Method not implemented."); - } - - readonly topics = { - in: "services:preview", - out: "services:preview:callback", - }; - - readonly options = { - unique: true, - ack: true, - }; - - validate(message: PreviewPubsubRequest): boolean { - return !!(message && message.document && message.output); - } - - async process(message: PreviewPubsubRequest): Promise { - logger.info(`${this.name} - Processing preview generation ${message.document.id}`); - - let res: PreviewPubsubCallback = { document: message.document, thumbnails: [] }; - try { - res = await this.generate(message); - } catch (err) { - logger.error(`${this.name} - Can't generate thumbnails ${err}`); - } - - logger.info( - `${this.name} - Generated ${res.thumbnails.length} thumbnails from ${ - message.document.filename || message.document.id - }`, - ); - - return res; - } - - async generate(message: PreviewPubsubRequest): Promise { - //Download original file - const readable = await this.storage.read(message.document.path, { - totalChunks: message.document.chunks, - encryptionAlgo: message.document.encryption_algo, - encryptionKey: message.document.encryption_key, - }); - if (!readable) { - return { document: message.document, thumbnails: [] }; - } - - const inputPath = getTmpFile(); - const writable = fs.createWriteStream(inputPath); - - readable.pipe(writable); - - await new Promise(r => { - writable.on("finish", r); - }); - - writable.end(); - - //Generate previews - let localThumbnails: ThumbnailResult[] = []; - - try { - localThumbnails = await this.service.previewProcess.generateThumbnails( - { path: inputPath, mime: message.document.mime, filename: message.document.filename }, - message.output, - true, - ); - } catch (err) { - logger.error(`${this.name} - Can't generate thumbnails ${err}`); - localThumbnails = []; - throw Error("Can't generate thumbnails."); - } - - const thumbnails: PreviewPubsubCallback["thumbnails"] = []; - - for (let i = 0; i < localThumbnails.length; i++) { - const uploadThumbnailPath = `${message.output.path.replace(/\/$/, "")}/${i}.png`; - const uploadThumbnail = fs.createReadStream(localThumbnails[i].path); - - await this.storage.write(uploadThumbnailPath, uploadThumbnail, { - encryptionAlgo: message.output.encryption_algo, - encryptionKey: message.output.encryption_key, - }); - - thumbnails.push({ - path: uploadThumbnailPath, - size: localThumbnails[i].size, - type: localThumbnails[i].type, - width: localThumbnails[i].width, - height: localThumbnails[i].height, - }); - - await unlink(localThumbnails[i].path); - } - - return { document: message.document, thumbnails }; - } -} diff --git a/twake/backend/node/src/services/previews/services/files/engine/clear.ts b/twake/backend/node/src/services/previews/services/files/engine/clear.ts new file mode 100644 index 0000000000..06749c4974 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/engine/clear.ts @@ -0,0 +1,48 @@ +import { logger, TwakeContext } from "../../../../../core/platform/framework"; +import { PreviewClearMessageQueueRequest, PreviewMessageQueueCallback } from "../../../types"; +import gr from "../../../../global-resolver"; +import { MessageQueueHandler } from "../../../../../core/platform/services/message-queue/api"; + +/** + * Clear thumbnails when the delete task is called + */ +export class ClearProcessor + implements MessageQueueHandler +{ + readonly name = "ClearProcessor"; + + readonly topics = { + in: "services:preview:clear", + out: "services:preview:callback", + }; + + readonly options = { + unique: true, + ack: true, + }; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + init?(context?: TwakeContext): Promise { + throw new Error("Method not implemented."); + } + + validate(message: PreviewClearMessageQueueRequest): boolean { + return !!(message && message.document); + } + + async process(message: PreviewClearMessageQueueRequest): Promise { + logger.info(`${this.name} - Processing preview generation ${message.document.id}`); + + if (!this.validate(message)) { + throw new Error("Missing required fields"); + } + + for (let i = 0; i < message.document.thumbnails_number; i++) { + await gr.platformServices.storage.remove( + `${message.document.path.replace(/\/$/, "")}/${i}.png`, + ); + } + + return { document: message.document, thumbnails: [] }; + } +} diff --git a/twake/backend/node/src/services/previews/services/files/engine/index.ts b/twake/backend/node/src/services/previews/services/files/engine/index.ts new file mode 100644 index 0000000000..0d04a2b5e9 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/engine/index.ts @@ -0,0 +1,15 @@ +import { Initializable } from "../../../../../core/platform/framework"; +import { ClearProcessor } from "./clear"; +import { PreviewProcessor } from "./service"; +import gr from "../../../../global-resolver"; + +/** + * The notification engine is in charge of processing data and delivering user notifications on the right place + */ +export class PreviewEngine implements Initializable { + async init(): Promise { + gr.platformServices.messageQueue.processor.addHandler(new PreviewProcessor()); + gr.platformServices.messageQueue.processor.addHandler(new ClearProcessor()); + return this; + } +} diff --git a/twake/backend/node/src/services/previews/services/files/engine/service.ts b/twake/backend/node/src/services/previews/services/files/engine/service.ts new file mode 100644 index 0000000000..3faeba5725 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/engine/service.ts @@ -0,0 +1,119 @@ +import fs, { promises as fsPromise } from "fs"; +import { logger, TwakeContext } from "../../../../../core/platform/framework"; +import { + PreviewMessageQueueCallback, + PreviewMessageQueueRequest, + ThumbnailResult, +} from "../../../types"; +import { getTmpFile } from "../../../utils"; +import gr from "../../../../global-resolver"; +import { MessageQueueHandler } from "../../../../../core/platform/services/message-queue/api"; + +const { unlink } = fsPromise; +/** + * Generate thumbnails when the upload is finished + */ +export class PreviewProcessor + implements MessageQueueHandler +{ + readonly name = "PreviewProcessor"; + + init?(context?: TwakeContext): Promise { + throw new Error("Method not implemented."); + } + + readonly topics = { + in: "services:preview", + out: "services:preview:callback", + }; + + readonly options = { + unique: true, + ack: true, + }; + + validate(message: PreviewMessageQueueRequest): boolean { + return !!(message && message.document && message.output); + } + + async process(message: PreviewMessageQueueRequest): Promise { + logger.info(`${this.name} - Processing preview generation ${message.document.id}`); + + let res: PreviewMessageQueueCallback = { document: message.document, thumbnails: [] }; + try { + res = await this.generate(message); + } catch (err) { + logger.error(`${this.name} - Can't generate thumbnails ${err}`); + } + + logger.info( + `${this.name} - Generated ${res.thumbnails.length} thumbnails from ${ + message.document.filename || message.document.id + }`, + ); + + return res; + } + + async generate(message: PreviewMessageQueueRequest): Promise { + //Download original file + const readable = await gr.platformServices.storage.read(message.document.path, { + totalChunks: message.document.chunks, + encryptionAlgo: message.document.encryption_algo, + encryptionKey: message.document.encryption_key, + }); + if (!readable) { + return { document: message.document, thumbnails: [] }; + } + + const inputPath = getTmpFile(); + const writable = fs.createWriteStream(inputPath); + + readable.pipe(writable); + + await new Promise(r => { + writable.on("finish", r); + }); + + writable.end(); + + //Generate previews + let localThumbnails: ThumbnailResult[] = []; + + try { + localThumbnails = await gr.services.preview.files.generateThumbnails( + { path: inputPath, mime: message.document.mime, filename: message.document.filename }, + message.output, + true, + ); + } catch (err) { + logger.error(`${this.name} - Can't generate thumbnails ${err}`); + localThumbnails = []; + throw Error("Can't generate thumbnails."); + } + + const thumbnails: PreviewMessageQueueCallback["thumbnails"] = []; + + for (let i = 0; i < localThumbnails.length; i++) { + const uploadThumbnailPath = `${message.output.path.replace(/\/$/, "")}/${i}.png`; + const uploadThumbnail = fs.createReadStream(localThumbnails[i].path); + + await gr.platformServices.storage.write(uploadThumbnailPath, uploadThumbnail, { + encryptionAlgo: message.output.encryption_algo, + encryptionKey: message.output.encryption_key, + }); + + thumbnails.push({ + path: uploadThumbnailPath, + size: localThumbnails[i].size, + type: localThumbnails[i].type, + width: localThumbnails[i].width, + height: localThumbnails[i].height, + }); + + await unlink(localThumbnails[i].path); + } + + return { document: message.document, thumbnails }; + } +} diff --git a/twake/backend/node/src/services/previews/services/files/processing/image.ts b/twake/backend/node/src/services/previews/services/files/processing/image.ts new file mode 100644 index 0000000000..0e4707aeb6 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/processing/image.ts @@ -0,0 +1,55 @@ +import sharp from "sharp"; +import { cleanFiles, getTmpFile } from "../../../utils"; +import { PreviewMessageQueueRequest, ThumbnailResult } from "../../../types"; +import { logger } from "../../../../../core/platform/framework/logger"; + +export async function generatePreview( + inputPaths: string[], + options: PreviewMessageQueueRequest["output"], + deleteInputFile: boolean, +): Promise<{ + output: ThumbnailResult[]; + done: boolean; + error?: string; +}> { + const output: ThumbnailResult[] = []; + + for (const inputPath of inputPaths) { + let result: sharp.OutputInfo; + const outputPath = getTmpFile(); + try { + const inputMetadata = await sharp(inputPath).metadata(); + const outputFormat = computeNewFormat(inputMetadata, options); + + result = await sharp(inputPath).rotate().resize(outputFormat).toFile(outputPath); + output.push({ + path: outputPath, + width: result.width, + height: result.height, + type: "image/png", + size: result.size, + }); + } catch (error) { + logger.info(`sharp cant process ${error}`); + cleanFiles([outputPath]); + throw Error("Can't resize thumnail with Sharp"); + } + } + + return { + output, + done: true, + }; +} + +function computeNewFormat( + inputMetadata: sharp.Metadata, + options?: PreviewMessageQueueRequest["output"], +): { width: number; height: number } { + const maxOutputWidth = options?.width || 600; + const maxOutputHeight = options?.height || 400; + const inputWidth = inputMetadata.width; + const inputHeight = inputMetadata.height; + const scale = Math.max(inputWidth / maxOutputWidth, inputHeight / maxOutputHeight); + return { width: Math.round(inputWidth / scale), height: Math.round(inputHeight / scale) }; +} diff --git a/twake/backend/node/src/services/previews/services/processing/mime.ts b/twake/backend/node/src/services/previews/services/files/processing/mime.ts similarity index 99% rename from twake/backend/node/src/services/previews/services/processing/mime.ts rename to twake/backend/node/src/services/previews/services/files/processing/mime.ts index dccc68b8a1..01df56dcd0 100644 --- a/twake/backend/node/src/services/previews/services/processing/mime.ts +++ b/twake/backend/node/src/services/previews/services/files/processing/mime.ts @@ -47,6 +47,18 @@ export const officeExtensions = [ ]; export const pdfExtensions = ["pdf"]; export const imageExtensions = ["jpeg", "jpg", "png", "webp", "avif", "tiff", "gif", "svg"]; +export const videoExtensions = [ + "mp4", + "webm", + "mkv", + "avi", + "mov", + "flv", + "wmv", + "mpg", + "mpeg", + "m4v", +]; const mimes: any = { "123": "application/vnd.lotus-1-2-3", diff --git a/twake/backend/node/src/services/previews/services/files/processing/office.ts b/twake/backend/node/src/services/previews/services/files/processing/office.ts new file mode 100644 index 0000000000..1ea108c113 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/processing/office.ts @@ -0,0 +1,29 @@ +// eslint-disable-next-line @typescript-eslint/no-var-requires +const unoconv = require("unoconv-promise"); +import { logger } from "../../../../../core/platform/framework/logger"; +import { cleanFiles } from "../../../utils"; + +export async function convertFromOffice( + path: string, + options: { + numberOfPages?: number; + }, +): Promise<{ output: string; done: boolean }> { + if (options.numberOfPages >= 1) { + const outputPath = `${path}.pdf`; + try { + await unoconv.run({ + file: path, + output: outputPath, + export: `PageRange=1-${options.numberOfPages}`, + }); + } catch (err) { + logger.error(`unoconv cant process ${err}`); + cleanFiles([outputPath]); + throw Error("Can't convert file with unoconv"); + } + return { output: outputPath, done: true }; + } else { + logger.error("Unoconv can't processe, number of pages lower than 1"); + } +} diff --git a/twake/backend/node/src/services/previews/services/processing/pdf.ts b/twake/backend/node/src/services/previews/services/files/processing/pdf.ts similarity index 85% rename from twake/backend/node/src/services/previews/services/processing/pdf.ts rename to twake/backend/node/src/services/previews/services/files/processing/pdf.ts index 977bd9aa9c..6d5cdb1e20 100644 --- a/twake/backend/node/src/services/previews/services/processing/pdf.ts +++ b/twake/backend/node/src/services/previews/services/files/processing/pdf.ts @@ -1,6 +1,7 @@ import { fromPath } from "pdf2pic"; -import { existsSync, mkdirSync } from "fs"; -import { cleanFiles, getTmpFile } from "../../utils"; +import { mkdirSync } from "fs"; +import { cleanFiles, getTmpFile } from "../../../utils"; +import fsys from "fs"; export async function convertFromPdf( inputPath: string, @@ -27,6 +28,9 @@ export async function convertFromPdf( ); } } catch (err) { + if (!pages.length) { + throw err; + } //Just no more page to convert } } catch (error) { diff --git a/twake/backend/node/src/services/previews/services/files/processing/service.ts b/twake/backend/node/src/services/previews/services/files/processing/service.ts new file mode 100644 index 0000000000..090fdf4e61 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/processing/service.ts @@ -0,0 +1,68 @@ +import { generatePreview as thumbnailsFromImages } from "./image"; +import { convertFromOffice } from "./office"; +import { convertFromPdf } from "./pdf"; +import { cleanFiles, isFileType } from "../../../utils"; +import { imageExtensions, officeExtensions, pdfExtensions, videoExtensions } from "./mime"; +import { PreviewMessageQueueRequest, ThumbnailResult } from "../../../types"; +import { generateVideoPreview } from "./video"; +import { Initializable, TwakeServiceProvider } from "../../../../../core/platform/framework"; + +export class PreviewProcessService implements TwakeServiceProvider, Initializable { + name: "PreviewProcessService"; + version: "1"; + + async init() { + return this; + } + + async generateThumbnails( + document: Pick, + options: PreviewMessageQueueRequest["output"], + deleteTmpFile: boolean, + ): Promise { + if (isFileType(document.mime, document.filename, officeExtensions)) { + const pdfPath = await convertFromOffice(document.path, { + numberOfPages: options.pages, + }); + await cleanFiles([document.path]); + const thumbnailPath = await convertFromPdf(pdfPath.output, { + numberOfPages: options.pages, + }); + await cleanFiles([pdfPath.output]); + const images = (await thumbnailsFromImages(thumbnailPath.output, options, deleteTmpFile)) + .output; + await cleanFiles(thumbnailPath.output); + return images; + } + + if (isFileType(document.mime, document.filename, pdfExtensions)) { + const thumbnailPath = await convertFromPdf(document.path, { + numberOfPages: options.pages, + }); + await cleanFiles([document.path]); + const images = (await thumbnailsFromImages(thumbnailPath.output, options, deleteTmpFile)) + .output; + await cleanFiles(thumbnailPath.output); + return images; + } + + if (isFileType(document.mime, document.filename, imageExtensions)) { + const images = (await thumbnailsFromImages([document.path], options, deleteTmpFile)).output; + await cleanFiles([document.path]); + return images; + } + + if (isFileType(document.mime, document.filename, videoExtensions)) { + try { + const images = await generateVideoPreview([document.path]); + await cleanFiles([document.path]); + + return images; + } catch (error) { + throw Error("failed to generate video preview"); + } + } + + throw "Can not proccess, file type can't be defined"; + } +} diff --git a/twake/backend/node/src/services/previews/services/files/processing/video.ts b/twake/backend/node/src/services/previews/services/files/processing/video.ts new file mode 100644 index 0000000000..e09a680b6d --- /dev/null +++ b/twake/backend/node/src/services/previews/services/files/processing/video.ts @@ -0,0 +1,167 @@ +import ffmpeg from "fluent-ffmpeg"; +import { temporaryThumbnailFile, ThumbnailResult } from "../../../types"; +import { cleanFiles, getTmpFile } from "../../../utils"; +import fs from "fs"; + +/** + * Generate thumbnails for given video files. + * + * @param {String[]} videoPaths - the input video paths + * @returns {Promise} - resolves when the thumbnails are generated + */ +export async function generateVideoPreview(videoPaths: string[]): Promise { + const output: ThumbnailResult[] = []; + + for (const videoPath of videoPaths) { + const { fileName, folder, filePath } = getTemporaryThumbnailFile(); + + try { + const { width, height } = await takeVideoScreenshot(videoPath, folder, fileName); + + output.push({ + ...getThumbnailInformation(filePath), + width, + height, + }); + } catch (error) { + cleanFiles([filePath]); + throw Error(`failed to generate video preview: ${error}`); + } + } + + return output; +} + +/** + * Generate one thumbnail from a single video file. + * the thumbnail is the first frame from the video + * + * @param {String} inputPath - the input video Path + * @param {String} outputFolder - the output folder + * @param {String} outputFile - the output file name + * @returns {Primise} - resolves when the thumbnail is generated + */ +const takeVideoScreenshot = async ( + inputPath: string, + outputFolder: string, + outputFile: string, +): Promise<{ width: number; height: number }> => { + return new Promise(async (resolve, reject) => { + try { + const { width, height } = await getVideoDimensions(inputPath); + const { width: outputWidth, height: outputHeight } = calculateThumbnailDimensions( + width, + height, + ); + + ffmpeg(inputPath) + .screenshot({ + count: 1, + filename: outputFile, + folder: outputFolder, + timemarks: ["0"], + size: `${outputWidth}x${outputHeight}`, + }) + .on("end", () => { + resolve({ width: outputWidth, height: outputHeight }); + }) + .on("error", error => { + reject(error); + }); + } catch (error) { + reject(error); + } + }); +}; + +/** + * Get the generated thumbnail information. + * + * @param {String} path - the path to the thumbnail + * @param {PreviewMessageQueueRequest["output"]} options - the options for the thumbnails + * @returns { { path: string, type: string, size: number } } - the thumbnail information + */ +const getThumbnailInformation = ( + path: string, +): { + path: string; + type: string; + size: number; +} => { + const stats = fs.statSync(path); + + return { + size: stats.size, + type: "image/jpg", + path, + }; +}; + +/** + * generate a temporary thumbnail file. + * + * @returns {temporaryThumbnailFile} - the temporary thumbnail file information + */ +const getTemporaryThumbnailFile = (): temporaryThumbnailFile => { + const filePath = `${getTmpFile()}.jpg`; + const fileName = filePath.split("/").pop(); + const folder = filePath.substring(0, filePath.lastIndexOf("/")); + + return { + folder, + fileName, + filePath, + }; +}; + +/** + * Detect video dimensions + * + * @param {String} videoPath - the video path + * @returns {Promise<{ width: number, height: number }>} - the video dimensions + */ +async function getVideoDimensions(videoPath: string): Promise<{ width: number; height: number }> { + return new Promise((resolve, reject) => { + ffmpeg.ffprobe(videoPath, (err, metadata) => { + if (err) { + reject(err); + } + + const { width, height } = metadata.streams[0]; + resolve({ width, height }); + }); + }); +} + +/** + * Calculate the thumbnail dimensions. + * maximum dimension is 1080p and the minimum dimension is 320x240. + * The aspect ratio is preserved. + * + * @param {Number} width - the video width + * @param {Number} height - the video height + * @returns { { width: number, height: number } } - the thumbnail dimensions + */ +function calculateThumbnailDimensions( + width: number, + height: number, +): { + width: number; + height: number; +} { + let newWidth = Math.min(width, 1920); + let newHeight = Math.min(height, 1080); + const ratio = width / height; + + if (width > 1920 || height > 1080) { + newWidth = Math.min(1920, width); + newHeight = Math.min(1080, newWidth / ratio); + } + + if (width < 320 || height < 240) { + newWidth = Math.max(320, width); + newHeight = Math.max(240, newWidth / ratio); + } + + return { width: newWidth, height: newHeight }; +} diff --git a/twake/backend/node/src/services/previews/services/index.ts b/twake/backend/node/src/services/previews/services/index.ts deleted file mode 100644 index 1ed2cf26f4..0000000000 --- a/twake/backend/node/src/services/previews/services/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { PreviewServiceAPI } from "../api"; -import { DatabaseServiceAPI } from "../../../core/platform/services/database/api"; -import { PubsubServiceAPI } from "../../../core/platform/services/pubsub/api"; -import StorageAPI from "../../../core/platform/services/storage/provider"; -import { PreviewEngine } from "./engine"; -import { getService as getPreviewProcessService } from "./processing/index"; -import { PreviewProcessService } from "./processing/service"; - -export function getService( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - storage: StorageAPI, -): PreviewServiceAPI { - return getServiceInstance(databaseService, pubsub, storage); -} - -function getServiceInstance( - databaseService: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - storage: StorageAPI, -): PreviewServiceAPI { - return new Service(databaseService, pubsub, storage); -} -class Service implements PreviewServiceAPI { - version: "1"; - engine: PreviewEngine; - previewProcess: PreviewProcessService; - pubsub: PubsubServiceAPI; - - constructor( - readonly database: DatabaseServiceAPI, - pubsub: PubsubServiceAPI, - readonly storage: StorageAPI, - ) { - this.previewProcess = getPreviewProcessService(storage); - this.engine = new PreviewEngine(this, pubsub, storage); - this.pubsub = pubsub; - } - - async init(): Promise { - try { - await this.engine.init(); - } catch (err) { - console.error("Error while initializing preview service", err); - } - return this; - } -} diff --git a/twake/backend/node/src/services/previews/services/links/engine/index.ts b/twake/backend/node/src/services/previews/services/links/engine/index.ts new file mode 100644 index 0000000000..8f857fa36e --- /dev/null +++ b/twake/backend/node/src/services/previews/services/links/engine/index.ts @@ -0,0 +1,11 @@ +import { Initializable } from "../../../../../core/platform/framework"; +import { LinkPreviewProcessor } from "./service"; +import gr from "../../../../global-resolver"; + +export class LinkPreviewEngine implements Initializable { + async init(): Promise { + gr.platformServices.messageQueue.processor.addHandler(new LinkPreviewProcessor()); + + return this; + } +} diff --git a/twake/backend/node/src/services/previews/services/links/engine/service.ts b/twake/backend/node/src/services/previews/services/links/engine/service.ts new file mode 100644 index 0000000000..48210cf3d7 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/links/engine/service.ts @@ -0,0 +1,80 @@ +import { + LinkPreview, + LinkPreviewMessageQueueCallback, + LinkPreviewMessageQueueRequest, +} from "../../../types"; +import { logger, TwakeContext } from "../../../../../core/platform/framework"; +import gr from "../../../../global-resolver"; +import { MessageQueueHandler } from "../../../../../core/platform/services/message-queue/api"; + +export class LinkPreviewProcessor + implements MessageQueueHandler +{ + readonly name = "LinkPreviewProcessor"; + + readonly topics = { + in: "services:preview:links", + out: "services:preview:links:callback", + }; + + readonly options = { + unique: true, + ack: true, + }; + + init?(context?: TwakeContext): Promise { + throw new Error("Method not implemented."); + } + + /** + * Checks if the message is valid + * + * @param {LinkPreviewMessageQueueRequest} message - The message to check + * @returns {Boolean} - true if the message is valid + */ + validate(message: LinkPreviewMessageQueueRequest): boolean { + return !!(message && message.links && message.links.length); + } + + /** + * process the links preview generation message + * + * @param {LinkPreviewMessageQueueRequest} message - The message to process + * @returns {Promise} - links preview callback + */ + async process(message: LinkPreviewMessageQueueRequest): Promise { + logger.info(`${this.name} - Processing preview generation for ${message.links.length} links`); + + let res: LinkPreviewMessageQueueCallback = { previews: [], message: message.message }; + + try { + res = await this.generate(message); + } catch (err) { + logger.error(`${this.name} - Can't generate link previews ${err}`); + } + + logger.info(`${this.name} - Generated ${res.previews.length} link previews`); + + return res; + } + + /** + * Generate previews for links + * + * @param {LinkPreviewMessageQueueRequest} message - The message to process + * @returns {Promise} - links preview callback + */ + async generate( + message: LinkPreviewMessageQueueRequest, + ): Promise { + let previews: LinkPreview[] = []; + try { + previews = await gr.services.preview.links.generatePreviews(message.links); + } catch (err) { + logger.error(`${this.name} - Can't generate link previews ${err}`); + throw Error(`cannot generate link previews: ${err}`); + } + + return { previews, message: message.message }; + } +} diff --git a/twake/backend/node/src/services/previews/services/links/processing/image.ts b/twake/backend/node/src/services/previews/services/links/processing/image.ts new file mode 100644 index 0000000000..77a6c3f3f2 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/links/processing/image.ts @@ -0,0 +1,37 @@ +import { LinkPreview } from "../../../types"; +import { logger } from "../../../../../core/platform/framework"; +import imageProbe from "probe-image-size"; +import { getUrlFavicon, getDomain } from "../../../utils"; + +/** + * Generate a preview for a given image url. + * + * @param {String} url - the input url + * @returns {Promise} - resolves when the preview is generated + */ +export const generateImageUrlPreview = async (url: string): Promise => { + try { + const favicon = (await getUrlFavicon(getWebsiteUrl(url))) || null; + const domain = getDomain(url); + const title = url.split("/").pop(); + const { height: img_height, width: img_width } = await imageProbe(url); + + return { + title, + domain, + favicon, + url, + img_height, + img_width, + description: null, + img: url, + }; + } catch (error) { + logger.error(`failed to generate image url preview: ${error}`); + } +}; + +const getWebsiteUrl = (url: string) => { + const urlObj = new URL(url); + return `${urlObj.protocol}//${urlObj.hostname}`; +}; diff --git a/twake/backend/node/src/services/previews/services/links/processing/link.ts b/twake/backend/node/src/services/previews/services/links/processing/link.ts new file mode 100644 index 0000000000..292699fbb0 --- /dev/null +++ b/twake/backend/node/src/services/previews/services/links/processing/link.ts @@ -0,0 +1,77 @@ +import { parser } from "html-metadata-parser"; +import { LinkPreview } from "../../../types"; +import { logger } from "../../../../../core/platform/framework"; +import imageProbe from "probe-image-size"; +import { getUrlFavicon, getDomain, TIMEOUT, MAX_SIZE } from "../../../utils"; +import ua from "random-useragent"; + +type HtmlImage = { + src: string; +}; + +/** + * Generate a thumbnail for a given url. + * + * @param {String[]} urls - the input urls + * @returns {Promise} - resolves when the preview is generated + */ +export async function generateLinkPreview(url: string): Promise { + try { + return await getUrlInformation(url); + } catch (error) { + logger.error(`failed to generate link preview: ${error}`); + } +} + +/** + * get url information + * + * @param {String} url - the input url + * @returns {Promise} - resolves when the information is retrieved + */ +const getUrlInformation = async (url: string): Promise => { + try { + const parsedPage = await parser(url, { + timeout: TIMEOUT, + maxContentLength: MAX_SIZE, + headers: { + "User-Agent": ua.getRandom(), + }, + }); + const title = parsedPage.og?.title || parsedPage.meta?.title || null; + const description = parsedPage.og?.description || parsedPage.meta?.description || null; + let img = parsedPage.og?.image || parsedPage.meta?.image || parsedPage.images?.[0] || null; + + if (!title && !description && !img) { + throw new Error("not enough information to generate link preview"); + } + + const favicon = (await getUrlFavicon(url)) || null; + const domain = getDomain(url); + let img_height: number | null = null, + img_width: number | null = null; + + if (img) { + if (typeof img === "object") { + img = (img as HtmlImage).src; + } + + const dimensions = await imageProbe(img); + img_height = dimensions.height; + img_width = dimensions.width; + } + + return { + title, + domain, + description, + favicon, + img, + img_height, + img_width, + url, + }; + } catch (error) { + throw Error(`failed to get url information: ${error}`); + } +}; diff --git a/twake/backend/node/src/services/previews/services/links/processing/service.ts b/twake/backend/node/src/services/previews/services/links/processing/service.ts new file mode 100644 index 0000000000..7a38236dec --- /dev/null +++ b/twake/backend/node/src/services/previews/services/links/processing/service.ts @@ -0,0 +1,52 @@ +import { LinkPreview, LinkPreviewMessageQueueRequest } from "../../../types"; +import { generateLinkPreview } from "./link"; +import { checkUrlContents } from "../../../utils"; +import { generateImageUrlPreview } from "./image"; +import { + Initializable, + logger, + TwakeServiceProvider, +} from "../../../../../core/platform/framework"; + +export class LinkPreviewProcessService implements TwakeServiceProvider, Initializable { + name: "LinkPreviewProcessService"; + version: "1"; + + async init(): Promise { + return this; + } + + /** + * Generate previews for links + * + * @param {LinkPreviewMessageQueueRequest["links"]} links - input urls + * @returns {Promise} - The generated url previews + */ + async generatePreviews(links: LinkPreviewMessageQueueRequest["links"]): Promise { + const result: LinkPreview[] = []; + + for (const link of links) { + try { + const contentType = await checkUrlContents(link); + + if (!contentType) { + continue; + } + + if (contentType.includes("text/html")) { + result.push(await generateLinkPreview(link)); + } + + if (contentType.startsWith("image")) { + result.push(await generateImageUrlPreview(link)); + } + } catch (error) { + logger.error(`failed to generate link preview: ${error}`); + } + } + + return result.filter( + preview => preview && (preview.title || preview.description || preview.img), + ); + } +} diff --git a/twake/backend/node/src/services/previews/services/processing/image.ts b/twake/backend/node/src/services/previews/services/processing/image.ts deleted file mode 100644 index b760971d80..0000000000 --- a/twake/backend/node/src/services/previews/services/processing/image.ts +++ /dev/null @@ -1,55 +0,0 @@ -import sharp from "sharp"; -import { cleanFiles, getTmpFile } from "../../utils"; -import { PreviewPubsubRequest, ThumbnailResult } from "../../types"; -import { logger } from "../../../../core/platform/framework/logger"; - -export async function generatePreview( - inputPaths: string[], - options: PreviewPubsubRequest["output"], - deleteInputFile: boolean, -): Promise<{ - output: ThumbnailResult[]; - done: boolean; - error?: string; -}> { - const output: ThumbnailResult[] = []; - - for (const inputPath of inputPaths) { - var result: sharp.OutputInfo; - const outputPath = getTmpFile(); - try { - const inputMetadata = await sharp(inputPath).metadata(); - const outputFormat = computeNewFormat(inputMetadata, options); - - result = await sharp(inputPath).resize(outputFormat).toFile(outputPath); - output.push({ - path: outputPath, - width: result.width, - height: result.height, - type: "image/png", - size: result.size, - }); - } catch (error) { - logger.info(`sharp cant process ${error}`); - cleanFiles([outputPath]); - throw Error("Can't resize thumnail with Sharp"); - } - } - - return { - output, - done: true, - }; -} - -function computeNewFormat( - inputMetadata: sharp.Metadata, - options?: PreviewPubsubRequest["output"], -): { width: number; height: number } { - const maxOutputWidth = options?.width || 300; - const maxOutputHeight = options?.height || 200; - const inputWidth = inputMetadata.width; - const inputHeight = inputMetadata.height; - const scale = Math.max(inputWidth / maxOutputWidth, inputHeight / maxOutputHeight); - return { width: Math.round(inputWidth / scale), height: Math.round(inputHeight / scale) }; -} diff --git a/twake/backend/node/src/services/previews/services/processing/index.ts b/twake/backend/node/src/services/previews/services/processing/index.ts deleted file mode 100644 index 5747de91c6..0000000000 --- a/twake/backend/node/src/services/previews/services/processing/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { PreviewProcessService } from "./service"; -import StorageAPI from "../../../../core/platform/services/storage/provider"; - -export function getService(storage: StorageAPI): PreviewProcessService { - return new PreviewProcessService(storage); -} diff --git a/twake/backend/node/src/services/previews/services/processing/office.ts b/twake/backend/node/src/services/previews/services/processing/office.ts deleted file mode 100644 index 583653cd41..0000000000 --- a/twake/backend/node/src/services/previews/services/processing/office.ts +++ /dev/null @@ -1,28 +0,0 @@ -const unoconv = require("unoconv-promise"); -import { logger } from "../../../../core/platform/framework/logger"; -import { cleanFiles } from "../../utils"; - -export async function convertFromOffice( - path: string, - options: { - numberOfPages?: number; - }, -): Promise<{ output: string; done: boolean }> { - if (options.numberOfPages >= 1) { - const outputPath = `${path}.pdf`; - try { - await unoconv.run({ - file: path, - output: outputPath, - export: `PageRange=1-${options.numberOfPages}`, - }); - } catch (err) { - logger.error(`unoconv cant process ${err}`); - cleanFiles([outputPath]); - throw Error("Can't convert file with unoconv"); - } - return { output: outputPath, done: true }; - } else { - logger.error(`Unoconv can't processe, number of pages lower than 1`); - } -} diff --git a/twake/backend/node/src/services/previews/services/processing/service.ts b/twake/backend/node/src/services/previews/services/processing/service.ts deleted file mode 100644 index 38ffae895b..0000000000 --- a/twake/backend/node/src/services/previews/services/processing/service.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { generatePreview as thumbnailsFromImages } from "./image"; -import { convertFromOffice } from "./office"; -import { convertFromPdf } from "./pdf"; -import { cleanFiles, isFileType } from "../../utils"; -import { pdfExtensions, officeExtensions, imageExtensions } from "./mime"; -import StorageAPI from "../../../../core/platform/services/storage/provider"; -import { PreviewPubsubRequest, ThumbnailResult } from "../../types"; - -export class PreviewProcessService { - name: "PreviewProcessService"; - version: "1"; - - constructor(readonly storage: StorageAPI) {} - - async generateThumbnails( - document: Pick, - options: PreviewPubsubRequest["output"], - deleteTmpFile: boolean, - ): Promise { - if (isFileType(document.mime, document.filename, officeExtensions)) { - const pdfPath = await convertFromOffice(document.path, { - numberOfPages: options.pages, - }); - await cleanFiles([document.path]); - const thumbnailPath = await convertFromPdf(pdfPath.output, { - numberOfPages: options.pages, - }); - await cleanFiles([pdfPath.output]); - const images = (await thumbnailsFromImages(thumbnailPath.output, options, deleteTmpFile)) - .output; - await cleanFiles(thumbnailPath.output); - return images; - } - - if (isFileType(document.mime, document.filename, pdfExtensions)) { - const thumbnailPath = await convertFromPdf(document.path, { - numberOfPages: options.pages, - }); - await cleanFiles([document.path]); - const images = (await thumbnailsFromImages(thumbnailPath.output, options, deleteTmpFile)) - .output; - await cleanFiles(thumbnailPath.output); - return images; - } - - if (isFileType(document.mime, document.filename, imageExtensions)) { - const images = (await thumbnailsFromImages([document.path], options, deleteTmpFile)).output; - await cleanFiles([document.path]); - return images; - } - - throw "Can not proccess, file type can't be defined"; - } -} diff --git a/twake/backend/node/src/services/previews/types.ts b/twake/backend/node/src/services/previews/types.ts index c55a3eb69a..5232ef3761 100644 --- a/twake/backend/node/src/services/previews/types.ts +++ b/twake/backend/node/src/services/previews/types.ts @@ -1,4 +1,6 @@ -export type PreviewPubsubRequest = { +import { MessageLocalEvent } from "../messages/types"; + +export type PreviewMessageQueueRequest = { document: { id: string; provider: string; @@ -20,7 +22,7 @@ export type PreviewPubsubRequest = { }; }; -export type PreviewClearPubsubRequest = { +export type PreviewClearMessageQueueRequest = { document: { id: string; provider: string; @@ -29,7 +31,7 @@ export type PreviewClearPubsubRequest = { }; }; -export type PreviewPubsubCallback = { +export type PreviewMessageQueueCallback = { document: { id: string; path: string; @@ -53,3 +55,30 @@ export type ThumbnailResult = { size: number; type: string; }; + +export type temporaryThumbnailFile = { + filePath: string; + fileName: string; + folder: string; +}; + +export type LinkPreview = { + title: string; + description: string | null; + domain: string; + favicon: string | null; + img: string | null; + img_height: number | null; + img_width: number | null; + url: string; +}; + +export type LinkPreviewMessageQueueRequest = { + links: string[]; + message: MessageLocalEvent; +}; + +export type LinkPreviewMessageQueueCallback = { + message: MessageLocalEvent; + previews: LinkPreview[]; +}; diff --git a/twake/backend/node/src/services/previews/utils.ts b/twake/backend/node/src/services/previews/utils.ts index dbc7cf2925..a0c1cc183f 100644 --- a/twake/backend/node/src/services/previews/utils.ts +++ b/twake/backend/node/src/services/previews/utils.ts @@ -1,7 +1,12 @@ import { v4 as uuidv4 } from "uuid"; -import mimes from "./services/processing/mime"; -import fs, { existsSync } from "fs"; -import { promises as fsPromise } from "fs"; +import mimes from "./services/files/processing/mime"; +import fs, { existsSync, promises as fsPromise } from "fs"; +import getFavicons from "get-website-favicon"; +import { logger } from "../../core/platform/framework"; +import axios from "axios"; + +export const TIMEOUT = 5 * 1000; +export const MAX_SIZE = 5 * 1024 * 1024; const { unlink } = fsPromise; @@ -23,3 +28,56 @@ export async function cleanFiles(paths: string[]) { if (existsSync(path)) await unlink(path); } } + +/** + * get url favicon + * + * @param {String} url - the input url + * @returns {Promise} - resolves when the favicon is retrieved + */ +export const getUrlFavicon = async (url: string): Promise => { + try { + const result = await getFavicons(url); + if (!result.icons || !result.icons.length) { + return; + } + + return result.icons[0].src; + } catch (error) { + logger.error(`failed to get url favicon: ${error}`); + } +}; + +/** + * Get domain from a given url. + * + * @param {String} url - the input url + * @returns {String} - resolves when the domain is retrieved + */ +export const getDomain = (url: string): string => { + try { + const domain = new URL(url).hostname; + return domain.replace(/^www\./, ""); + } catch (error) { + throw Error(`failed to get domain: ${error}`); + } +}; + +/** + * Get url content type headers + * + * @param {string} url - the input url + * @returns {Promise} - the request headers + */ +export const checkUrlContents = async (url: string): Promise => { + try { + const response = await axios(url, { + maxContentLength: MAX_SIZE, + timeout: TIMEOUT, + }); + + return response.headers["content-type"]; + } catch (error) { + throw Error(`failed to check url contents: ${error}`); + } +}; diff --git a/twake/backend/node/src/services/previews/web/controllers/previews.ts b/twake/backend/node/src/services/previews/web/controllers/previews.ts index 5af4a059b0..21fa83a057 100644 --- a/twake/backend/node/src/services/previews/web/controllers/previews.ts +++ b/twake/backend/node/src/services/previews/web/controllers/previews.ts @@ -1,5 +1 @@ -import { PreviewServiceAPI } from "../../api"; - -export class PreviewController { - constructor(protected service: PreviewServiceAPI) {} -} +export class PreviewController {} diff --git a/twake/backend/node/src/services/previews/web/index.ts b/twake/backend/node/src/services/previews/web/index.ts index 3790b61b98..07be98c4e2 100644 --- a/twake/backend/node/src/services/previews/web/index.ts +++ b/twake/backend/node/src/services/previews/web/index.ts @@ -1,12 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { PreviewServiceAPI } from "../api"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: PreviewServiceAPI; }>, ) => { fastify.log.debug("Configuring /internal/services/previews/v1 routes"); diff --git a/twake/backend/node/src/services/previews/web/routes.ts b/twake/backend/node/src/services/previews/web/routes.ts index 5bd4801686..47a27d6451 100644 --- a/twake/backend/node/src/services/previews/web/routes.ts +++ b/twake/backend/node/src/services/previews/web/routes.ts @@ -1,15 +1,10 @@ import { FastifyInstance, FastifyPluginCallback } from "fastify"; -import { PreviewServiceAPI } from "../api"; import { PreviewController } from "./controllers/previews"; const previewsUrl = "/previews"; -const routes: FastifyPluginCallback<{ service: PreviewServiceAPI }> = ( - fastify: FastifyInstance, - options, - next, -) => { - const previewController = new PreviewController(options.service); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const previewController = new PreviewController(); next(); }; diff --git a/twake/backend/node/src/services/statistics/index.ts b/twake/backend/node/src/services/statistics/index.ts index 7e405c14d0..78479bdd15 100644 --- a/twake/backend/node/src/services/statistics/index.ts +++ b/twake/backend/node/src/services/statistics/index.ts @@ -1,69 +1,15 @@ -import { Consumes, TwakeService } from "../../core/platform/framework"; -import { STATISTICS_GLOBAL_KEY, StatisticsAPI } from "./types"; -import { DatabaseServiceAPI } from "../../core/platform/services/database/api"; -import StatisticsEntity, { - getInstance as getStatisticsEntityInstance, - TYPE as StatisticsEntityType, -} from "./entities/statistics"; -import Repository from "../../core/platform/services/database/services/orm/repository/repository"; +import { TwakeService } from "../../core/platform/framework"; -@Consumes(["database"]) -export default class StatisticsService - extends TwakeService - implements StatisticsAPI -{ - name = "statistics"; +export default class StatisticService extends TwakeService { version = "1"; - private repository: Repository; - - api(): StatisticsAPI { - return this; - } + name = "statistics"; - async doInit(): Promise { - const database = this.context.getProvider("database"); - this.repository = await database.getRepository( - StatisticsEntityType, - StatisticsEntity, - ); + public async doInit(): Promise { return this; } - async increase(companyId: string, eventName: string, value: number = 1): Promise { - const now = new Date(); - const monthId = +(now.getFullYear() + now.getMonth().toString().padStart(2, "0")); // format 202108 - - //return Promise.all([ - await this.dbIncrement(STATISTICS_GLOBAL_KEY, eventName, monthId, value); - await this.dbIncrement(STATISTICS_GLOBAL_KEY, eventName, 0, value); - await this.dbIncrement(companyId, eventName, monthId, value); - await this.dbIncrement(companyId, eventName, 0, value); - //]).then(() => null); - } - - async get(companyId: string = STATISTICS_GLOBAL_KEY, eventName: string): Promise { - const res = await this.repository.findOne({ - company_id: companyId, - event_name: eventName, - month_id: 0, - }); - - return res?.value || 0; - } - - private dbIncrement( - companyId: string, - eventName: string, - monthId: number, - value: number = 1, - ): Promise { - const entity = getStatisticsEntityInstance({ - company_id: companyId, - event_name: eventName, - month_id: monthId, - }); - - entity.value = value; - return this.repository.save(entity); + // TODO: remove + api(): undefined { + return undefined; } } diff --git a/twake/backend/node/src/services/statistics/pubsub/messages.ts b/twake/backend/node/src/services/statistics/pubsub/messages.ts index b46fcafdaa..1a489e5f5f 100644 --- a/twake/backend/node/src/services/statistics/pubsub/messages.ts +++ b/twake/backend/node/src/services/statistics/pubsub/messages.ts @@ -1,13 +1,11 @@ -import { PubsubHandler } from "../../../core/platform/services/pubsub/api"; +import { MessageQueueHandler } from "../../../core/platform/services/message-queue/api"; import { getLogger } from "../../../core/platform/framework"; import { MessageNotification } from "../../messages/types"; -import { StatisticsAPI } from "../types"; +import gr from "../../global-resolver"; -const logger = getLogger("statistics.pubsub.messages"); - -export class StatisticsMessageProcessor implements PubsubHandler { - constructor(readonly service: StatisticsAPI) {} +const logger = getLogger("statistics.messages"); +export class StatisticsMessageProcessor implements MessageQueueHandler { readonly topics = { in: "message:created", }; @@ -27,7 +25,7 @@ export class StatisticsMessageProcessor implements PubsubHandler { logger.info(`${this.name} - Processing increasing messages counter for ${message.company_id}`); try { - await this.service.increase(message.company_id, "messages"); + await gr.services.statistics.increase(message.company_id, "messages"); } catch (err) { logger.error( { err }, diff --git a/twake/backend/node/src/services/statistics/service/index.ts b/twake/backend/node/src/services/statistics/service/index.ts new file mode 100644 index 0000000000..f1048c6e46 --- /dev/null +++ b/twake/backend/node/src/services/statistics/service/index.ts @@ -0,0 +1,69 @@ +import { STATISTICS_GLOBAL_KEY } from "../types"; +import StatisticsEntity, { + getInstance as getStatisticsEntityInstance, + TYPE as StatisticsEntityType, +} from "../entities/statistics"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import gr from "../../global-resolver"; +import { Initializable, TwakeServiceProvider } from "../../../core/platform/framework"; +import { ExecutionContext } from "../../../core/platform/framework/api/crud-service"; + +export class StatisticsServiceImpl implements TwakeServiceProvider, Initializable { + version: "1"; + private repository: Repository; + + async init(): Promise { + this.repository = await gr.database.getRepository( + StatisticsEntityType, + StatisticsEntity, + ); + return this; + } + + async increase(companyId: string, eventName: string, value: number = 1): Promise { + const now = new Date(); + const monthId = +(now.getFullYear() + now.getMonth().toString().padStart(2, "0")); // format 202108 + + //return Promise.all([ + await this.dbIncrement(STATISTICS_GLOBAL_KEY, eventName, monthId, value); + await this.dbIncrement(STATISTICS_GLOBAL_KEY, eventName, 0, value); + await this.dbIncrement(companyId, eventName, monthId, value); + await this.dbIncrement(companyId, eventName, 0, value); + //]).then(() => null); + } + + async get( + companyId: string = STATISTICS_GLOBAL_KEY, + eventName: string, + context?: ExecutionContext, + ): Promise { + const res = await this.repository.findOne( + { + company_id: companyId, + event_name: eventName, + month_id: 0, + }, + {}, + context, + ); + + return res?.value || 0; + } + + private dbIncrement( + companyId: string, + eventName: string, + monthId: number, + value: number = 1, + context?: ExecutionContext, + ): Promise { + const entity = getStatisticsEntityInstance({ + company_id: companyId, + event_name: eventName, + month_id: monthId, + }); + + entity.value = value; + return this.repository.save(entity, context); + } +} diff --git a/twake/backend/node/src/services/statistics/types.ts b/twake/backend/node/src/services/statistics/types.ts index a1b9adf0b3..493236eb8c 100644 --- a/twake/backend/node/src/services/statistics/types.ts +++ b/twake/backend/node/src/services/statistics/types.ts @@ -1,6 +1,6 @@ -import { TwakeServiceProvider } from "../../core/platform/framework"; +import { Initializable, TwakeServiceProvider } from "../../core/platform/framework"; -export interface StatisticsAPI extends TwakeServiceProvider { +export interface StatisticsAPI extends TwakeServiceProvider, Initializable { increase(companyId: string, eventName: string, value?: number): Promise; get(companyId: string | null, eventName: string): Promise; } diff --git a/twake/backend/node/src/services/user/api.ts b/twake/backend/node/src/services/user/api.ts deleted file mode 100644 index 3ef2bf9b70..0000000000 --- a/twake/backend/node/src/services/user/api.ts +++ /dev/null @@ -1,168 +0,0 @@ -import { - CRUDService, - DeleteResult, - ExecutionContext, - ListResult, - Paginable, - SaveResult, -} from "../../core/platform/framework/api/crud-service"; -import { Initializable, TwakeServiceProvider } from "../../core/platform/framework/api"; -import User, { UserPrimaryKey } from "./entities/user"; -import CompanyUser, { CompanyUserPrimaryKey } from "./entities/company_user"; -import Company, { CompanyPrimaryKey, CompanySearchKey } from "./entities/company"; -import ExternalUser from "./entities/external_user"; -import ExternalGroup from "./entities/external_company"; -import { ListUserOptions } from "./services/users/types"; -import { - CompanyObject, - CompanyStatsObject, - CompanyUserObject, - CompanyUserRole, - UserObject, -} from "./web/types"; -import { WorkspaceServiceAPI } from "../workspaces/api"; -import { uuid } from "../../utils/types"; -import Device from "./entities/device"; -import { StatisticsAPI } from "../statistics/types"; - -export default interface UserServiceAPI extends TwakeServiceProvider, Initializable { - users: UsersServiceAPI; - companies: CompaniesServiceAPI; - workspaces: WorkspaceServiceAPI; - external: UserExternalLinksServiceAPI; - statistics: StatisticsAPI; - - formatUser(user: User, options?: { includeCompanies?: boolean }): Promise; - formatCompany( - companyEntity: Company, - companyUserObject?: CompanyUserObject, - companyStats?: CompanyStatsObject, - ): CompanyObject; -} - -export interface UsersServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - getUserCompanies(pk: UserPrimaryKey): Promise; - - search( - pagination: Paginable, - options?: ListOptions, - context?: ExecutionContext, - ): Promise>; - - getByEmail(email: string): Promise; - getByEmails(email: string[]): Promise; - getByConsoleId(consoleUserId: string): Promise; - isEmailAlreadyInUse(email: string): Promise; - getAvailableUsername(username: string): Promise; - getUserDevices(userPrimaryKey: UserPrimaryKey): Promise; - registerUserDevice( - userPrimaryKey: UserPrimaryKey, - token: string, - type: string, - version: string, - ): Promise; - deregisterUserDevice(token: string): Promise; - setPassword(userPrimaryKey: UserPrimaryKey, password: string): Promise; - getHashedPassword(userPrimaryKey: UserPrimaryKey): Promise<[string, string]>; - anonymizeAndDelete(user: UserPrimaryKey, context?: ExecutionContext): Promise; - setPreferences( - user: UserPrimaryKey, - preferences: User["preferences"], - ): Promise; -} - -/** - * Service to manage links between external and internal users/companies. - */ -export interface UserExternalLinksServiceAPI extends TwakeServiceProvider, Initializable { - /** - * Create a external user link - * - * @param user - */ - createExternalUser(user: ExternalUser): Promise; - - /** - * Create an external group link - * - * @param group - */ - createExternalGroup(group: ExternalGroup): Promise; -} -export interface CompaniesServiceAPI extends TwakeServiceProvider, Initializable { - /** - * Create a company - * - * @param company - */ - createCompany(company: Company): Promise; - updateCompany(company: Company): Promise>; - - /** - * Get a company from its id or identity - * - * @param companySearchKey - */ - getCompany(companySearchKey: CompanySearchKey): Promise; - - /** - * Get the companies - * - * @param pagination - */ - getCompanies(pagination?: Paginable): Promise>; - - /** - * Get all companies for a user - * @param company - * @param user - */ - getAllForUser(userId: uuid): Promise; - - /** - * Add a user in a company - * - * @param company - * @param user - */ - removeUserFromCompany( - companyId: CompanyPrimaryKey, - user: UserPrimaryKey, - ): Promise>; - - /** - * Get user ids in the given company - * - * @param companyId - * @param pagination - */ - getUsers( - companyId: CompanyUserPrimaryKey, - pagination?: Paginable, - options?: ListUserOptions, - ): Promise>; - - /** - * Get company user - * @param company - * @param user - */ - getCompanyUser(company: CompanyPrimaryKey, user: UserPrimaryKey): Promise; - - delete(pk: CompanyPrimaryKey, context?: ExecutionContext): Promise>; - - setUserRole( - companyId: uuid, - userId: uuid, - role?: CompanyUserRole, - ): Promise>; - - getUserRole(companyId: uuid, userId: uuid): Promise; - - removeCompany(searchKey: CompanySearchKey): Promise; - - getUsersCount(workspaceId: string): Promise; -} diff --git a/twake/backend/node/src/services/user/entities/company.ts b/twake/backend/node/src/services/user/entities/company.ts index c60c83f640..8473a55bcc 100644 --- a/twake/backend/node/src/services/user/entities/company.ts +++ b/twake/backend/node/src/services/user/entities/company.ts @@ -1,5 +1,6 @@ import { merge } from "lodash"; import { Column, Entity } from "../../../core/platform/services/database/services/orm/decorators"; +import { CompanyFeaturesObject, CompanyLimitsObject } from "../web/types"; // backward compatibility with PHP where companies used to be `group_entity` export const TYPE = "group_entity"; @@ -21,7 +22,8 @@ export default class Company { @Column("plan", "encoded_json") plan?: { name: string; - features: any; + limits: CompanyLimitsObject; + features: CompanyFeaturesObject; }; @Column("stats", "encoded_json") diff --git a/twake/backend/node/src/services/user/entities/company_user.ts b/twake/backend/node/src/services/user/entities/company_user.ts index 85569462a8..3d9c1a5219 100644 --- a/twake/backend/node/src/services/user/entities/company_user.ts +++ b/twake/backend/node/src/services/user/entities/company_user.ts @@ -23,7 +23,10 @@ export default class CompanyUser { id: string; @Column("role", "string") - role: CompanyUserRole; + role: CompanyUserRole = "member"; + + @Column("applications", "json") + applications: string[] = []; @Column("nb_workspace", "number") nbWorkspaces: number; diff --git a/twake/backend/node/src/services/user/entities/device.ts b/twake/backend/node/src/services/user/entities/device.ts index 1e4cdc4c61..dfb5943d84 100644 --- a/twake/backend/node/src/services/user/entities/device.ts +++ b/twake/backend/node/src/services/user/entities/device.ts @@ -20,6 +20,9 @@ export default class Device { @Column("version", "string") version: string; + + @Column("push_notifications", "boolean") + push_notifications: boolean; } export type UserDevicePrimaryKey = Pick; diff --git a/twake/backend/node/src/services/user/entities/user.search.ts b/twake/backend/node/src/services/user/entities/user.search.ts index 78fc586d60..373c167eab 100644 --- a/twake/backend/node/src/services/user/entities/user.search.ts +++ b/twake/backend/node/src/services/user/entities/user.search.ts @@ -4,12 +4,11 @@ import User from "./user"; export default { index: "user", source: (entity: User) => { - const expanded = `${entity.first_name} ${entity.last_name} ${entity.email_canonical}`; - let source: any = { + const source: any = { first_name: entity.first_name, last_name: entity.last_name, - email_canonical: entity.email_canonical, - expanded: expandStringForPrefix(expanded), + email: entity.email_canonical, + username: entity.username_canonical, }; if (entity.cache?.companies) { return { @@ -23,18 +22,23 @@ export default { text: { first_name: "text", last_name: "text", - email_canonical: "text", - expanded: "text", + email: "text", + username: "text", + }, + prefix: { + first_name: "prefix", + last_name: "prefix", + email: "prefix", + username: "prefix", }, }, esMapping: { properties: { - first_name: { type: "text" }, - last_name: { type: "text" }, - email_canonical: { type: "text" }, - expanded: { type: "text" }, + first_name: { type: "text", index_prefixes: { min_chars: 1 } }, + last_name: { type: "text", index_prefixes: { min_chars: 1 } }, + email: { type: "text", index_prefixes: { min_chars: 1 } }, + username: { type: "text", index_prefixes: { min_chars: 1 } }, companies: { type: "keyword" }, - workspaces: { type: "keyword" }, }, }, }; diff --git a/twake/backend/node/src/services/user/entities/user.ts b/twake/backend/node/src/services/user/entities/user.ts index 34de074a24..aa7987bfe5 100644 --- a/twake/backend/node/src/services/user/entities/user.ts +++ b/twake/backend/node/src/services/user/entities/user.ts @@ -7,7 +7,7 @@ export const TYPE = "user"; @Entity(TYPE, { primaryKey: [["id"]], - globalIndexes: [["email_canonical"]], + globalIndexes: [["email_canonical"], ["username_canonical"]], type: TYPE, search, }) @@ -30,6 +30,7 @@ export default class User { public get status_icon(): string { if (this._status_icon && this._status_icon.startsWith("[\\")) { try { + // eslint-disable-next-line quotes const parsed = JSON.parse(this._status_icon.replace(/\\"/g, '"').replace(/\\\\/g, "\\")); return `${parsed[0]} ${parsed[1]}`; } catch (e) { @@ -93,11 +94,15 @@ export default class User { @Column("preferences", "encoded_json") preferences: null | { + locale?: string; timezone?: number; language?: string; allow_tracking?: boolean; tutorial_done?: boolean; channel_ordering?: "chronological" | "alphabetical"; + recent_workspaces?: { company_id: string; workspace_id: string }[]; + knowledge_graph?: "all" | "nothing" | "metadata"; + notifications?: UserNotificationPreferences[]; }; @Column("cache", "encoded_json") @@ -116,6 +121,24 @@ export default class User { } } +export type UserNotificationPreferences = { + company_id: string | "all"; + workspace_id: string | "all"; + preferences: { + highlight_words?: string[]; + night_break?: { + enable: boolean; + from: number; + to: number; + }; + private_message_content?: boolean; + mobile_notifications?: "never" | "when_inactive" | "always"; + email_notifications_delay?: number; //0: never send email, 1 and more in minutes from first unread notification + deactivate_notifications_until?: number; + notification_sound?: "default" | "none" | string; + }; +}; + export type UserPrimaryKey = Pick; export function getInstance(user: Partial): User { diff --git a/twake/backend/node/src/services/user/index.ts b/twake/backend/node/src/services/user/index.ts index 8aeae2a28d..90bbd4d96e 100644 --- a/twake/backend/node/src/services/user/index.ts +++ b/twake/backend/node/src/services/user/index.ts @@ -1,38 +1,23 @@ -import { Consumes, Prefix, TwakeService } from "../../core/platform/framework"; -import UserServiceAPI from "./api"; -import web from "./web/index"; -import { getService } from "./services"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../applications/api"; -import { StatisticsAPI } from "../statistics/types"; -import AuthServiceAPI from "../../core/platform/services/auth/provider"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; +import { Prefix, TwakeService } from "../../core/platform/framework"; +import WebServerAPI from "../../core/platform/services/webserver/provider"; +import web from "./web"; @Prefix("/internal/services/users/v1") -@Consumes(["platform-services", "applications", "statistics", "auth", "realtime"]) -export default class UserService extends TwakeService { +export default class UserService extends TwakeService { version = "1"; name = "user"; - private service: UserServiceAPI; public async doInit(): Promise { - const platformServices = this.context.getProvider("platform-services"); - const applications = this.context.getProvider("applications"); - const statistics = this.context.getProvider("statistics"); - const auth = this.context.getProvider("auth"); - const realtime = this.context.getProvider("realtime"); - - this.service = getService(platformServices, applications, statistics, auth); - - await this.service?.init(this.context); - platformServices.fastify.getServer().register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + const fastify = this.context.getProvider("webserver").getServer(); + fastify.register((instance, _opts, next) => { + web(instance, { prefix: this.prefix }); next(); }); return this; } - api(): UserServiceAPI { - return this.service; + // TODO: remove + api(): undefined { + return undefined; } } diff --git a/twake/backend/node/src/services/user/services/companies.ts b/twake/backend/node/src/services/user/services/companies.ts new file mode 100644 index 0000000000..7ed2bae0f5 --- /dev/null +++ b/twake/backend/node/src/services/user/services/companies.ts @@ -0,0 +1,357 @@ +import _, { merge } from "lodash"; + +import { + CrudException, + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Paginable, + Pagination, + SaveResult, +} from "../../../core/platform/framework/api/crud-service"; +import Repository, { + FindOptions, +} from "../../../core/platform/services/database/services/orm/repository/repository"; +import { UserPrimaryKey } from "../entities/user"; +import Company, { + CompanyPrimaryKey, + CompanySearchKey, + getInstance as getCompanyInstance, +} from "../entities/company"; +import CompanyUser, { + CompanyUserPrimaryKey, + getInstance as getCompanyUserInstance, +} from "../entities/company_user"; +import { ListUserOptions } from "./users/types"; +import { CompanyUserRole } from "../web/types"; +import { ResourceEventsPayload, uuid } from "../../../utils/types"; +import ExternalGroup, { + ExternalGroupPrimaryKey, + getInstance as getExternalGroupInstance, +} from "../entities/external_company"; +import { logger, RealtimeSaved } from "../../../core/platform/framework"; +import { getCompanyRoom, getUserRoom } from "../realtime"; +import gr from "../../global-resolver"; +import { localEventBus } from "../../../core/platform/framework/event-bus"; +import { + KnowledgeGraphEvents, + KnowledgeGraphGenericEventPayload, +} from "../../../core/platform/services/knowledge-graph/types"; + +export class CompanyServiceImpl { + version: "1"; + companyRepository: Repository; + externalCompanyRepository: Repository; + companyUserRepository: Repository; + + async init(): Promise { + this.companyRepository = await gr.database.getRepository("group_entity", Company); + this.companyUserRepository = await gr.database.getRepository( + "group_user", + CompanyUser, + ); + this.externalCompanyRepository = await gr.database.getRepository( + "external_group_repository", + ExternalGroup, + ); + + return this; + } + + private getExtCompany(pk: ExternalGroupPrimaryKey, context?: ExecutionContext) { + return this.externalCompanyRepository.findOne(pk, {}, context); + } + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + @RealtimeSaved((company, _context) => { + return [ + { + room: getCompanyRoom(company.id), + resource: company, + }, + ]; + }) + async updateCompany( + company: Company, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + _options?: SaveOptions, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + context?: ExecutionContext, + ): Promise> { + if (company.identity_provider_id && !company.identity_provider) { + company.identity_provider = "console"; + } + + await this.companyRepository.save(company, context); + + if (company.identity_provider_id) { + const key = { + service_id: company.identity_provider, + external_id: company.identity_provider_id, + }; + + const extCompany = (await this.getExtCompany(key, context)) || getExternalGroupInstance(key); + + extCompany.company_id = company.id; + extCompany.external_id = company.identity_provider_id; + extCompany.service_id = company.identity_provider; + + await this.externalCompanyRepository.save(extCompany, context); + } + + return new SaveResult("company", company, OperationType.UPDATE); + } + + async createCompany(company: Company, context?: ExecutionContext): Promise { + const companyToCreate: Company = getCompanyInstance({ + ...company, + ...{ + dateAdded: Date.now(), + }, + }); + + const result = await this.updateCompany(companyToCreate); + + localEventBus.publish>( + KnowledgeGraphEvents.COMPANY_CREATED, + { + id: result.entity.id, + resource: result.entity, + links: [{ relation: "owner", type: "user", id: result.context?.user.id }], + }, + ); + return result.entity; + } + + async getCompany( + companySearchKey: CompanySearchKey, + context?: ExecutionContext, + ): Promise { + if (companySearchKey.id) { + return this.companyRepository.findOne(companySearchKey, {}, context); + } else if (companySearchKey.identity_provider_id) { + const extCompany = await this.getExtCompany( + { + external_id: companySearchKey.identity_provider_id, + service_id: companySearchKey.identity_provider || "console", + }, + context, + ); + if (!extCompany) { + return null; + } + return await this.companyRepository.findOne({ id: extCompany.company_id }, {}, context); + } + } + + async getCompanyUser( + company: CompanyPrimaryKey, + user: UserPrimaryKey, + context?: ExecutionContext, + ): Promise { + const companyUser = await this.companyUserRepository.findOne( + { + group_id: company.id, + user_id: user.id, + }, + {}, + context, + ); + if (companyUser) companyUser.applications = []; + return companyUser; + } + + async getAllForUser(userId: uuid, context?: ExecutionContext): Promise { + const list = await this.companyUserRepository + .find({ user_id: userId }, {}, context) + .then(a => a.getEntities()); + + // Update user cache with companies + const user = await gr.services.users.get({ id: userId }); + if ( + user.cache?.companies.length === 0 || + _.difference( + list.map(c => c.group_id), + user.cache?.companies || [], + ).length != 0 + ) { + if (!user.cache) user.cache = { companies: [] }; + user.cache.companies = list.map(c => c.group_id); + await gr.services.users.save(user, { user: { id: user.id, server_request: true } }); + } + + return list; + } + + getCompanies(paginable?: Paginable, context?: ExecutionContext): Promise> { + return this.companyRepository.find( + {}, + { + pagination: new Pagination( + paginable?.page_token, + paginable?.limitStr || "100", + paginable?.reversed, + ), + }, + context, + ); + } + + @RealtimeSaved((companyUser, _) => { + return [ + { + room: getUserRoom(companyUser?.user_id), + resource: companyUser, + }, + ]; + }) + async removeUserFromCompany( + companyPk: CompanyPrimaryKey, + userPk: UserPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const entity = await this.companyUserRepository.findOne( + { + group_id: companyPk.id, + user_id: userPk.id, + }, + {}, + context, + ); + if (entity) { + await Promise.all([this.companyUserRepository.remove(entity, context)]); + + const user = await gr.services.users.get(userPk); + if ((user.cache?.companies || []).includes(companyPk.id)) { + // Update user cache with companies + user.cache.companies = user.cache.companies.filter(id => id != companyPk.id); + await gr.services.users.save(user, { user: { id: user.id, server_request: true } }); + } + + localEventBus.publish("company:user:deleted", { + user: user, + company: companyPk, + }); + } + + return new DeleteResult("company_user", entity, true); + } + + async getUsers( + companyId: CompanyUserPrimaryKey, + pagination?: Pagination, + options?: ListUserOptions, + context?: ExecutionContext, + ): Promise> { + const findOptions: FindOptions = { + pagination, + }; + + if (options?.userIds) { + findOptions.$in = [["user_id", options.userIds]]; + } + + return this.companyUserRepository.find({ group_id: companyId.group_id }, findOptions, context); + } + + async delete(pk: CompanyPrimaryKey, context?: ExecutionContext): Promise> { + const instance = await this.companyRepository.findOne(pk, {}, context); + if (instance) await this.companyRepository.remove(instance, context); + return new DeleteResult("company", instance, !!instance); + } + + @RealtimeSaved((companyUser, _) => { + return [ + { + room: getUserRoom(companyUser?.user_id), + resource: companyUser, + }, + ]; + }) + async setUserRole( + companyId: uuid, + userId: uuid, + role: CompanyUserRole = "member", + applications: string[] = [], + context?: ExecutionContext, + ): Promise> { + const key = { + group_id: companyId, + user_id: userId, + }; + let entity = await this.companyUserRepository.findOne(key, {}, context); + + if (entity == null) { + entity = getCompanyUserInstance(merge(key, { dateAdded: Date.now() })); + } + + entity.role = role; + entity.applications = applications; + await this.companyUserRepository.save(entity, context); + + const user = await gr.services.users.get({ id: userId }); + if (!(user.cache?.companies || []).includes(companyId)) { + // Update user cache with companies + if (!user.cache) user.cache = { companies: [] }; + user.cache.companies.push(companyId); + await gr.services.users.save(user, { user: { id: user.id, server_request: true } }); + } + + return new SaveResult("company_user", entity, OperationType.UPDATE); + } + + async removeCompany(searchKey: CompanySearchKey, context?: ExecutionContext): Promise { + if (searchKey.identity_provider_id) { + const extCompany = await this.getExtCompany( + { + service_id: searchKey.identity_provider, + external_id: searchKey.identity_provider_id, + }, + context, + ); + if (!extCompany) { + throw CrudException.notFound(`Company ${searchKey.identity_provider_id} not found`); + } + await this.externalCompanyRepository.remove(extCompany, context); + searchKey.id = extCompany.company_id; + } + + const company = await this.getCompany({ id: searchKey.id }); + if (!company) { + throw CrudException.notFound(`Company ${searchKey.id} not found`); + } + + await this.companyRepository.remove(company, context); + + return Promise.resolve(null); + } + + getUsersCount(companyId: string, context?: ExecutionContext): Promise { + return this.getCompany({ id: companyId }).then(a => a.memberCount); + } + + async getUserRole( + companyId: uuid, + userId: uuid, + context?: ExecutionContext, + ): Promise { + const companyUser = await this.getCompanyUser({ id: companyId }, { id: userId }); + if (!companyUser) { + return "guest"; + } + return companyUser.role; + } + + async ensureDeletedUserNotInCompanies(userPk: UserPrimaryKey, context?: ExecutionContext) { + const user = await gr.services.users.get(userPk); + if (user.deleted) { + const companies = await this.getAllForUser(user.id); + for (const company of companies) { + logger.warn(`User ${userPk.id} is deleted so removed from company ${company.id}`); + await this.removeUserFromCompany(company, user); + await gr.services.workspaces.ensureUserNotInCompanyIsNotInWorkspace(userPk, company.id); + } + } + } +} diff --git a/twake/backend/node/src/services/user/services/companies/index.ts b/twake/backend/node/src/services/user/services/companies/index.ts deleted file mode 100644 index 4f32abac15..0000000000 --- a/twake/backend/node/src/services/user/services/companies/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; -import UserServiceAPI, { CompaniesServiceAPI } from "../../api"; -import { CompanyService } from "./service"; -import { CounterAPI } from "../../../../core/platform/services/counter/types"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService( - platformServices: PlatformServicesAPI, - userServiceAPI: UserServiceAPI, -): CompaniesServiceAPI { - return new CompanyService(platformServices, userServiceAPI); -} diff --git a/twake/backend/node/src/services/user/services/companies/service.ts b/twake/backend/node/src/services/user/services/companies/service.ts deleted file mode 100644 index c41450a001..0000000000 --- a/twake/backend/node/src/services/user/services/companies/service.ts +++ /dev/null @@ -1,302 +0,0 @@ -import _, { merge } from "lodash"; - -import { - CrudExeption, - DeleteResult, - ExecutionContext, - ListResult, - OperationType, - Pagination, - SaveResult, -} from "../../../../core/platform/framework/api/crud-service"; -import Repository, { - FindOptions, -} from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { UserPrimaryKey } from "../../entities/user"; -import UserServiceAPI, { CompaniesServiceAPI } from "../../api"; -import Company, { - CompanyPrimaryKey, - CompanySearchKey, - getInstance as getCompanyInstance, -} from "../../entities/company"; -import CompanyUser, { - CompanyUserPrimaryKey, - getInstance as getCompanyUserInstance, -} from "../../entities/company_user"; -import { ListUserOptions } from "../users/types"; -import { CompanyUserRole } from "../../web/types"; -import { uuid } from "../../../../utils/types"; -import ExternalGroup, { - ExternalGroupPrimaryKey, - getInstance as getExternalGroupInstance, -} from "../../entities/external_company"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; -import { RealtimeDeleted, RealtimeSaved } from "../../../../core/platform/framework"; -import { getCompanyRoom, getUserRoom } from "../../realtime"; - -export class CompanyService implements CompaniesServiceAPI { - version: "1"; - companyRepository: Repository; - externalCompanyRepository: Repository; - companyUserRepository: Repository; - - constructor( - private platformServices: PlatformServicesAPI, - private userServiceAPI: UserServiceAPI, - ) {} - - async init(): Promise { - this.companyRepository = await this.platformServices.database.getRepository( - "group_entity", - Company, - ); - this.companyUserRepository = await this.platformServices.database.getRepository( - "group_user", - CompanyUser, - ); - this.externalCompanyRepository = - await this.platformServices.database.getRepository( - "external_group_repository", - ExternalGroup, - ); - - return this; - } - - private getExtCompany(pk: ExternalGroupPrimaryKey) { - return this.externalCompanyRepository.findOne(pk); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - @RealtimeSaved((company, _context) => { - return [ - { - room: getCompanyRoom(company.id), - resource: company, - }, - ]; - }) - async updateCompany( - company: Company, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _options?: SaveOptions, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - _context?: ExecutionContext, - ): Promise> { - if (company.identity_provider_id && !company.identity_provider) { - company.identity_provider = "console"; - } - - await this.companyRepository.save(company); - - if (company.identity_provider_id) { - const key = { - service_id: company.identity_provider, - external_id: company.identity_provider_id, - }; - - const extCompany = (await this.getExtCompany(key)) || getExternalGroupInstance(key); - - extCompany.company_id = company.id; - extCompany.external_id = company.identity_provider_id; - extCompany.service_id = company.identity_provider; - - await this.externalCompanyRepository.save(extCompany); - } - - return new SaveResult("company", company, OperationType.UPDATE); - } - - async createCompany(company: Company): Promise { - const companyToCreate: Company = getCompanyInstance({ - ...company, - ...{ - dateAdded: Date.now(), - }, - }); - - const result = await this.updateCompany(companyToCreate); - return result.entity; - } - - async getCompany(companySearchKey: CompanySearchKey): Promise { - if (companySearchKey.id) { - return this.companyRepository.findOne(companySearchKey); - } else if (companySearchKey.identity_provider_id) { - const extCompany = await this.getExtCompany({ - external_id: companySearchKey.identity_provider_id, - service_id: companySearchKey.identity_provider || "console", - }); - if (!extCompany) { - return null; - } - return await this.companyRepository.findOne({ id: extCompany.company_id }); - } - } - - getCompanyUser(company: CompanyPrimaryKey, user: UserPrimaryKey): Promise { - return this.companyUserRepository.findOne({ group_id: company.id, user_id: user.id }); - } - - async getAllForUser(userId: uuid): Promise { - const list = await this.companyUserRepository - .find({ user_id: userId }) - .then(a => a.getEntities()); - - // Update user cache with companies - const user = await this.userServiceAPI.users.get({ id: userId }); - if ( - user.cache?.companies.length === 0 || - _.difference( - list.map(c => c.group_id), - user.cache?.companies || [], - ).length != 0 - ) { - if (!user.cache) user.cache = { companies: [] }; - user.cache.companies = list.map(c => c.group_id); - await this.userServiceAPI.users.save( - user, - {}, - { user: { id: user.id, server_request: true } }, - ); - } - - return list; - } - - getCompanies(pagination?: Pagination): Promise> { - return this.companyRepository.find({}, { pagination }); - } - - @RealtimeSaved((companyUser, _) => { - return [ - { - room: getUserRoom(companyUser?.user_id), - resource: companyUser, - }, - ]; - }) - async removeUserFromCompany( - companyPk: CompanyPrimaryKey, - userPk: UserPrimaryKey, - ): Promise> { - const entity = await this.companyUserRepository.findOne({ - group_id: companyPk.id, - user_id: userPk.id, - }); - if (entity) { - await Promise.all([this.companyUserRepository.remove(entity)]); - - const user = await this.userServiceAPI.users.get(userPk); - if ((user.cache?.companies || []).includes(companyPk.id)) { - // Update user cache with companies - user.cache.companies = user.cache.companies.filter(id => id != companyPk.id); - await this.userServiceAPI.users.save( - user, - {}, - { user: { id: user.id, server_request: true } }, - ); - } - } - - return new DeleteResult("company_user", entity, true); - } - - async getUsers( - companyId: CompanyUserPrimaryKey, - pagination?: Pagination, - options?: ListUserOptions, - ): Promise> { - const findOptions: FindOptions = { - pagination, - }; - - if (options?.userIds) { - findOptions.$in = [["user_id", options.userIds]]; - } - - return this.companyUserRepository.find({ group_id: companyId.group_id }, findOptions); - } - - async delete(pk: CompanyPrimaryKey, context?: ExecutionContext): Promise> { - const instance = await this.companyRepository.findOne(pk); - if (instance) await this.companyRepository.remove(instance); - return new DeleteResult("company", instance, !!instance); - } - - @RealtimeSaved((companyUser, _) => { - return [ - { - room: getUserRoom(companyUser?.user_id), - resource: companyUser, - }, - ]; - }) - async setUserRole( - companyId: uuid, - userId: uuid, - role: CompanyUserRole = "member", - ): Promise> { - const key = { - group_id: companyId, - user_id: userId, - }; - let entity = await this.companyUserRepository.findOne(key); - - if (entity == null) { - entity = getCompanyUserInstance(merge(key, { dateAdded: Date.now() })); - } - - entity.role = role; - await this.companyUserRepository.save(entity); - - const user = await this.userServiceAPI.users.get({ id: userId }); - if (!(user.cache?.companies || []).includes(companyId)) { - // Update user cache with companies - if (!user.cache) user.cache = { companies: [] }; - user.cache.companies.push(companyId); - await this.userServiceAPI.users.save( - user, - {}, - { user: { id: user.id, server_request: true } }, - ); - } - - return new SaveResult("company_user", entity, OperationType.UPDATE); - } - - async removeCompany(searchKey: CompanySearchKey): Promise { - if (searchKey.identity_provider_id) { - const extCompany = await this.getExtCompany({ - service_id: searchKey.identity_provider, - external_id: searchKey.identity_provider_id, - }); - if (!extCompany) { - throw CrudExeption.notFound(`Company ${searchKey.identity_provider_id} not found`); - } - await this.externalCompanyRepository.remove(extCompany); - searchKey.id = extCompany.company_id; - } - - const company = await this.getCompany({ id: searchKey.id }); - if (!company) { - throw CrudExeption.notFound(`Company ${searchKey.id} not found`); - } - - await this.companyRepository.remove(company); - - return Promise.resolve(null); - } - - getUsersCount(companyId: string): Promise { - return this.getCompany({ id: companyId }).then(a => a.memberCount); - } - - async getUserRole(companyId: uuid, userId: uuid): Promise { - const companyUser = await this.getCompanyUser({ id: companyId }, { id: userId }); - if (!companyUser) { - return "guest"; - } - return companyUser.role; - } -} diff --git a/twake/backend/node/src/services/user/services/external_links/index.ts b/twake/backend/node/src/services/user/services/external_links/index.ts index 6a77124a60..18f60ea913 100644 --- a/twake/backend/node/src/services/user/services/external_links/index.ts +++ b/twake/backend/node/src/services/user/services/external_links/index.ts @@ -1,64 +1,66 @@ -import { DatabaseServiceAPI } from "../../../../core/platform/services/database/api"; import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; import ExternalUser from "../../entities/external_user"; import ExternalGroup from "../../entities/external_company"; -import { UserExternalLinksServiceAPI } from "../../api"; + import Company from "../../entities/company"; import User from "../../entities/user"; +import gr from "../../../global-resolver"; +import { ExecutionContext } from "../../../../core/platform/framework/api/crud-service"; -export class UserExternalLinksService implements UserExternalLinksServiceAPI { +export class UserExternalLinksServiceImpl { version: "1"; private externalUserRepository: Repository; private externalGroupRepository: Repository; private companyRepository: Repository; private userRepository: Repository; - constructor(private database: DatabaseServiceAPI) {} - async init(): Promise { - this.externalUserRepository = await this.database.getRepository( + this.externalUserRepository = await gr.database.getRepository( "external_user_repository", ExternalUser, ); - this.externalGroupRepository = await this.database.getRepository( + this.externalGroupRepository = await gr.database.getRepository( "external_group_repository", ExternalGroup, ); - this.companyRepository = await this.database.getRepository("group_entity", Company); - this.userRepository = await this.database.getRepository("user", User); + this.companyRepository = await gr.database.getRepository("group_entity", Company); + this.userRepository = await gr.database.getRepository("user", User); return this; } - async createExternalUser(user: ExternalUser): Promise { - await this.externalUserRepository.save(user); + async createExternalUser(user: ExternalUser, context?: ExecutionContext): Promise { + await this.externalUserRepository.save(user, context); //Save user provider and provider id here - const internalUser = await this.userRepository.findOne({ id: user.user_id }); + const internalUser = await this.userRepository.findOne({ id: user.user_id }, {}, context); if (internalUser) { internalUser.identity_provider = user.service_id; internalUser.identity_provider_id = user.external_id; - this.userRepository.save(internalUser); + this.userRepository.save(internalUser, context); } return user; } - async createExternalGroup(group: ExternalGroup): Promise { - await this.externalGroupRepository.save(group); + async createExternalGroup( + group: ExternalGroup, + context?: ExecutionContext, + ): Promise { + await this.externalGroupRepository.save(group, context); //Save company provider and provider id here - const internalCompany = await this.companyRepository.findOne({ id: group.company_id }); + const internalCompany = await this.companyRepository.findOne( + { id: group.company_id }, + {}, + context, + ); if (internalCompany) { internalCompany.identity_provider = group.service_id; internalCompany.identity_provider_id = group.external_id; - this.companyRepository.save(internalCompany); + this.companyRepository.save(internalCompany, context); } return group; } } - -export function getService(databaseService: DatabaseServiceAPI): UserExternalLinksServiceAPI { - return new UserExternalLinksService(databaseService); -} diff --git a/twake/backend/node/src/services/user/services/index.ts b/twake/backend/node/src/services/user/services/index.ts deleted file mode 100644 index 6f6ca612f6..0000000000 --- a/twake/backend/node/src/services/user/services/index.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { TwakeContext } from "../../../core/platform/framework"; -import UserServiceAPI, { - CompaniesServiceAPI, - UserExternalLinksServiceAPI, - UsersServiceAPI, -} from "../api"; -import { getService as getUserService } from "./users"; -import { getService as getCompanyService } from "./companies"; -import { getService as getExternalService } from "./external_links"; -import { getService as getWorkspaceService } from "../../workspaces/services/workspace"; -import { WorkspaceServiceAPI } from "../../workspaces/api"; -import { - CompanyObject, - CompanyShort, - CompanyStatsObject, - CompanyUserObject, - CompanyUserRole, - CompanyUserStatus, - UserObject, -} from "../web/types"; -import Company from "../entities/company"; -import User from "../entities/user"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../../applications/api"; -import { StatisticsAPI } from "../../statistics/types"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; - -export function getService( - platformServices: PlatformServicesAPI, - applications: ApplicationServiceAPI, - statistics: StatisticsAPI, - auth: AuthServiceAPI, -): UserServiceAPI { - return new Service(platformServices, applications, statistics, auth); -} - -class Service implements UserServiceAPI { - version: "1"; - users: UsersServiceAPI; - companies: CompaniesServiceAPI; - external: UserExternalLinksServiceAPI; - workspaces: WorkspaceServiceAPI; - - constructor( - platformServices: PlatformServicesAPI, - readonly applications: ApplicationServiceAPI, - readonly statistics: StatisticsAPI, - readonly auth: AuthServiceAPI, - ) { - this.users = getUserService(platformServices); - this.external = getExternalService(platformServices.database); - this.companies = getCompanyService(platformServices, this); - this.workspaces = getWorkspaceService( - platformServices, - this.users, - this.companies, - this.applications, - auth, - ); - } - - async init(context: TwakeContext): Promise { - try { - await Promise.all([ - this.users.init(context), - this.companies.init(context), - this.external.init(context), - this.workspaces.init(context), - ]); - } catch (err) { - console.error("Error while initializing user service", err); - } - return this; - } - - public async formatUser( - user: User, - options?: { includeCompanies?: boolean }, - ): Promise { - let resUser = { - id: user.id, - provider: user.identity_provider, - provider_id: user.identity_provider_id, - email: user.email_canonical, - username: user.username_canonical, - is_verified: Boolean(user.mail_verified), - picture: user.picture, - first_name: user.first_name, - last_name: user.last_name, - full_name: [user.first_name, user.last_name].join(" "), - created_at: user.creation_date, - deleted: Boolean(user.deleted), - status: user.status_icon, - last_activity: user.last_activity, - } as UserObject; - - if (options?.includeCompanies) { - const userCompanies = await this.users.getUserCompanies({ id: user.id }); - - const companies = await Promise.all( - userCompanies.map(async uc => { - const company = await this.companies.getCompany({ id: uc.group_id }); - return { - role: uc.role as CompanyUserRole, - status: "active" as CompanyUserStatus, // FIXME: with real status - company: { - id: uc.group_id, - name: company.name, - logo: company.logo, - } as CompanyShort, - } as CompanyUserObject; - }), - ); - - resUser = { - ...resUser, - preference: { - ...user.preferences, - locale: user.preferences?.language || user.language || "en", - timezone: user.preferences?.timezone || parseInt(user.timezone) || 0, - allow_tracking: user.preferences?.allow_tracking || false, - }, - - companies, - }; - } - - return resUser; - } - - public formatCompany( - companyEntity: Company, - companyUserObject?: CompanyUserObject, - companyStats?: CompanyStatsObject, - ): CompanyObject { - const res: CompanyObject = { - id: companyEntity.id, - name: companyEntity.name || "", - logo: companyEntity.logo || "", - plan: companyEntity.plan, - identity_provider: companyEntity.identity_provider, - identity_provider_id: companyEntity.identity_provider_id, - }; - - if (companyUserObject) { - res.status = "active"; // FIXME: with real status - res.role = companyUserObject.role; - } - - if (companyStats) { - res.stats = companyStats; - } - - return res; - } -} diff --git a/twake/backend/node/src/services/user/services/users/index.ts b/twake/backend/node/src/services/user/services/users/index.ts deleted file mode 100644 index 1a78d0459f..0000000000 --- a/twake/backend/node/src/services/user/services/users/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { UserService } from "./service"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; - -export function getService(platformServices: PlatformServicesAPI): UserService { - return new UserService(platformServices); -} diff --git a/twake/backend/node/src/services/user/services/users/service.ts b/twake/backend/node/src/services/user/services/users/service.ts index dc0823b01d..b80ccbff65 100644 --- a/twake/backend/node/src/services/user/services/users/service.ts +++ b/twake/backend/node/src/services/user/services/users/service.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/ban-ts-comment */ import { CreateResult, - CrudExeption, + CrudException, DeleteResult, ExecutionContext, ListResult, @@ -14,8 +14,7 @@ import Repository, { FindFilter, FindOptions, } from "../../../../core/platform/services/database/services/orm/repository/repository"; -import User, { getInstance, UserPrimaryKey } from "../../entities/user"; -import { UsersServiceAPI } from "../../api"; +import User, { UserPrimaryKey } from "../../entities/user"; import { ListUserOptions, SearchUserOptions } from "./types"; import CompanyUser from "../../entities/company_user"; import SearchRepository from "../../../../core/platform/services/search/repository"; @@ -26,49 +25,58 @@ import Device, { } from "../../entities/device"; import PasswordEncoder from "../../../../utils/password-encoder"; import assert from "assert"; -import { localEventBus } from "../../../../core/platform/framework/pubsub"; +import { localEventBus } from "../../../../core/platform/framework/event-bus"; import { ResourceEventsPayload } from "../../../../utils/types"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; -import { isNumber } from "lodash"; +import { isNumber, isString } from "lodash"; import { RealtimeSaved } from "../../../../core/platform/framework"; import { getUserRoom } from "../../realtime"; +import NodeCache from "node-cache"; +import gr from "../../../global-resolver"; +import { + KnowledgeGraphEvents, + KnowledgeGraphGenericEventPayload, +} from "../../../../core/platform/services/knowledge-graph/types"; -export class UserService implements UsersServiceAPI { +export class UserServiceImpl { version: "1"; repository: Repository; searchRepository: SearchRepository; companyUserRepository: Repository; extUserRepository: Repository; private deviceRepository: Repository; - - constructor(private platformServices: PlatformServicesAPI) {} + private cache: NodeCache; async init(): Promise { - this.searchRepository = this.platformServices.search.getRepository("user", User); - this.repository = await this.platformServices.database.getRepository("user", User); - this.companyUserRepository = await this.platformServices.database.getRepository( + this.searchRepository = gr.platformServices.search.getRepository("user", User); + this.repository = await gr.database.getRepository("user", User); + this.companyUserRepository = await gr.database.getRepository( "group_user", CompanyUser, ); - this.extUserRepository = await this.platformServices.database.getRepository( + this.extUserRepository = await gr.database.getRepository( "external_user_repository", ExternalUser, ); - this.deviceRepository = await this.platformServices.database.getRepository( - DeviceType, - Device, - ); + this.deviceRepository = await gr.database.getRepository(DeviceType, Device); + + this.cache = new NodeCache({ stdTTL: 0.2, checkperiod: 120 }); + + //If user deleted from Twake, remove it from all companies + localEventBus.subscribe("user:deleted", async data => { + if (data?.user?.id) gr.services.companies.ensureDeletedUserNotInCompanies(data.user); + }); return this; } - private async updateExtRepository(user: User) { + private async updateExtRepository(user: User, context?: ExecutionContext) { if (user.identity_provider_id) { const key = { service_id: user.identity_provider, external_id: user.identity_provider_id }; - const extUser = (await this.extUserRepository.findOne(key)) || getExternalUserInstance(key); + const extUser = + (await this.extUserRepository.findOne(key, {}, context)) || getExternalUserInstance(key); extUser.user_id = user.id; - await this.extUserRepository.save(extUser); + await this.extUserRepository.save(extUser, context); } } @@ -77,14 +85,36 @@ export class UserService implements UsersServiceAPI { if (user.identity_provider_id && !user.identity_provider) user.identity_provider = "console"; if (user.email_canonical) user.email_canonical = user.email_canonical.toLocaleLowerCase(); if (user.username_canonical) - user.username_canonical = user.username_canonical.toLocaleLowerCase(); + user.username_canonical = (user.username_canonical || "") + .toLocaleLowerCase() + .replace(/[^a-z0-9_-]/, ""); } - async create(user: User): Promise> { + async create(user: User, context?: ExecutionContext): Promise> { this.assignDefaults(user); - await this.repository.save(user); + + await this.repository.save(user, context); await this.updateExtRepository(user); - return new CreateResult("user", user); + const result = new CreateResult("user", user); + + if (result) { + localEventBus.publish>( + KnowledgeGraphEvents.USER_CREATED, + { + id: result.entity.id, + resource: result.entity, + links: [ + { + // FIXME: We should provide the company id here + id: "", + relation: "parent", + type: "company", + }, + ], + }, + ); + } + return result; } update(pk: Partial, item: User, context?: ExecutionContext): Promise> { @@ -99,20 +129,16 @@ export class UserService implements UsersServiceAPI { }, ]; }) - async save( - user: User, - options?: SaveOptions, - context?: ExecutionContext, - ): Promise> { + async save(user: User, context?: ExecutionContext): Promise> { this.assignDefaults(user); - await this.repository.save(user); + await this.repository.save(user, context); await this.updateExtRepository(user); return new SaveResult("user", user, OperationType.UPDATE); } async delete(pk: Partial, context?: ExecutionContext): Promise> { - const instance = await this.repository.findOne(pk); - if (instance) await this.repository.remove(instance); + const instance = await this.repository.findOne(pk, {}, context); + if (instance) await this.repository.remove(instance, context); return new DeleteResult("user", instance, !!instance); } @@ -156,6 +182,7 @@ export class UserService implements UsersServiceAPI { $search: options.search, }, }, + context, ); } @@ -173,14 +200,14 @@ export class UserService implements UsersServiceAPI { findOptions.$in = [["id", options.userIds]]; } - return this.repository.find(findFilter, findOptions); + return this.repository.find(findFilter, findOptions, context); } - getByEmail(email: string): Promise { - return this.repository.findOne({ email_canonical: email }); + getByEmail(email: string, context?: ExecutionContext): Promise { + return this.repository.findOne({ email_canonical: email }, {}, context); } - getByEmails(emails: string[]): Promise { + getByEmails(emails: string[], context?: ExecutionContext): Promise { return Promise.all(emails.map(email => this.getByEmail(email))).then(emails => emails.filter(a => a), ); @@ -189,40 +216,72 @@ export class UserService implements UsersServiceAPI { async setPreferences( pk: UserPrimaryKey, preferences: User["preferences"], + context?: ExecutionContext, ): Promise { - const user = await this.repository.findOne(pk); + const user = await this.repository.findOne(pk, {}, context); if (!user.preferences) user.preferences = {}; for (const key in preferences) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore user.preferences[key] = preferences[key]; } + + await this.save(user); return user.preferences; } - async get(pk: UserPrimaryKey): Promise { - return await this.repository.findOne(pk); + async get(pk: UserPrimaryKey, context?: ExecutionContext): Promise { + return await this.repository.findOne(pk, {}, context); + } + + async getCached(pk: UserPrimaryKey, context?: ExecutionContext): Promise { + if (!(pk.id && isString(pk.id))) return null; + if (this.cache.has(pk.id)) return this.cache.get(pk.id); + const entity = await this.get(pk); + this.cache.set(pk.id, entity); + return entity; + } + + async getByUsername(username: string, context?: ExecutionContext): Promise { + return await this.repository.findOne( + { + username_canonical: (username || "").toLocaleLowerCase(), + }, + {}, + context, + ); } - async getByConsoleId(id: string, service_id: string = "console"): Promise { - const extUser = await this.extUserRepository.findOne({ service_id, external_id: id }); + async getByConsoleId( + id: string, + service_id: string = "console", + context?: ExecutionContext, + ): Promise { + const extUser = await this.extUserRepository.findOne( + { service_id, external_id: id }, + {}, + context, + ); if (!extUser) { return null; } - return this.repository.findOne({ id: extUser.user_id }); + return this.repository.findOne({ id: extUser.user_id }, {}, context); } - async getUserCompanies(pk: UserPrimaryKey): Promise { - return await this.companyUserRepository.find({ user_id: pk.id }).then(a => a.getEntities()); + async getUserCompanies(pk: UserPrimaryKey, context?: ExecutionContext): Promise { + return await this.companyUserRepository + .find({ user_id: pk.id }, {}, context) + .then(a => a.getEntities()); } - async isEmailAlreadyInUse(email: string): Promise { - return this.repository.findOne({ email_canonical: email }).then(user => Boolean(user)); + async isEmailAlreadyInUse(email: string, context?: ExecutionContext): Promise { + return this.repository + .findOne({ email_canonical: email }, {}, context) + .then(user => Boolean(user)); } - async getAvailableUsername(username: string): Promise { - const users = await this.repository.find({}).then(a => a.getEntities()); + async getAvailableUsername(username: string, context?: ExecutionContext): Promise { + const user = await this.getByUsername(username); - if (!users.find(user => user.username_canonical == username.toLocaleLowerCase())) { + if (!user) { return username; } @@ -230,7 +289,7 @@ export class UserService implements UsersServiceAPI { for (let i = 1; i < 1000; i++) { const dynamicUsername = username + i; - if (!users.find(user => user.username_canonical == dynamicUsername.toLocaleLowerCase())) { + if (!(await this.getByUsername(dynamicUsername.toLocaleLowerCase()))) { suitableUsername = dynamicUsername; break; } @@ -238,17 +297,20 @@ export class UserService implements UsersServiceAPI { return suitableUsername; } - async getUserDevices(userPrimaryKey: UserPrimaryKey): Promise { + async getUserDevices( + userPrimaryKey: UserPrimaryKey, + context?: ExecutionContext, + ): Promise { const user = await this.get(userPrimaryKey); if (!user) { - throw CrudExeption.notFound(`User ${userPrimaryKey} not found`); + throw CrudException.notFound(`User ${userPrimaryKey} not found`); } if (!user.devices || user.devices.length == 0) { return []; } - return Promise.all(user.devices.map(id => this.deviceRepository.findOne({ id }))).then(a => - a.filter(a => a), - ); + return Promise.all( + user.devices.map(id => this.deviceRepository.findOne({ id }, {}, context)), + ).then(a => a.filter(a => a)); } async registerUserDevice( @@ -256,49 +318,60 @@ export class UserService implements UsersServiceAPI { id: string, type: string, version: string, + context?: ExecutionContext, ): Promise { await this.deregisterUserDevice(id); const user = await this.get(userPrimaryKey); if (!user) { - throw CrudExeption.notFound(`User ${userPrimaryKey} not found`); + throw CrudException.notFound(`User ${userPrimaryKey} not found`); } user.devices = user.devices || []; user.devices.push(id); - await this.repository.save(user); - await this.deviceRepository.save(getDeviceInstance({ id, type, version, user_id: user.id })); + await this.repository.save(user, context); + await this.deviceRepository.save( + getDeviceInstance({ id, type, version, user_id: user.id }), + context, + ); } - async deregisterUserDevice(id: string): Promise { - const existedDevice = await this.deviceRepository.findOne({ id }); + async deregisterUserDevice(id: string, context?: ExecutionContext): Promise { + const existedDevice = await this.deviceRepository.findOne({ id }, {}, context); if (existedDevice) { const user = await this.get({ id: existedDevice.user_id }); if (user) { user.devices = (user.devices || []).filter(d => d !== id); - await this.repository.save(user); + await this.repository.save(user, context); } - await this.deviceRepository.remove(existedDevice); + await this.deviceRepository.remove(existedDevice, context); } } - async setPassword(userPrimaryKey: UserPrimaryKey, password: string): Promise { + async setPassword( + userPrimaryKey: UserPrimaryKey, + password: string, + context?: ExecutionContext, + ): Promise { assert(password, "UserAPI.setPassword: Password is not defined"); const passwordEncoder = new PasswordEncoder(); const user = await this.get(userPrimaryKey); if (!user) { - throw CrudExeption.notFound(`User ${userPrimaryKey.id} not found`); + throw CrudException.notFound(`User ${userPrimaryKey.id} not found`); } user.password = await passwordEncoder.encodePassword(password); user.salt = null; - await this.repository.save(user); + await this.repository.save(user, context); } - async getHashedPassword(userPrimaryKey: UserPrimaryKey): Promise<[string, string]> { + async getHashedPassword( + userPrimaryKey: UserPrimaryKey, + context?: ExecutionContext, + ): Promise<[string, string]> { const user = await this.get(userPrimaryKey); if (!user) { - throw CrudExeption.notFound(`User ${userPrimaryKey.id} not found`); + throw CrudException.notFound(`User ${userPrimaryKey.id} not found`); } if (user.salt) { diff --git a/twake/backend/node/src/services/user/services/users/types.ts b/twake/backend/node/src/services/user/services/users/types.ts index 3339e294db..18a8d75287 100644 --- a/twake/backend/node/src/services/user/services/users/types.ts +++ b/twake/backend/node/src/services/user/services/users/types.ts @@ -6,4 +6,5 @@ export type SearchUserOptions = { search?: string; companyId?: string; workspaceId?: string; + channelId?: string; }; diff --git a/twake/backend/node/src/services/user/utils.ts b/twake/backend/node/src/services/user/utils.ts new file mode 100644 index 0000000000..dfa73a87d1 --- /dev/null +++ b/twake/backend/node/src/services/user/utils.ts @@ -0,0 +1,74 @@ +import Company from "./entities/company"; +import { + CompanyFeaturesEnum, + CompanyLimitsEnum, + CompanyObject, + CompanyStatsObject, + CompanyUserObject, +} from "./web/types"; + +export function formatCompany( + companyEntity: Company, + companyUserObject?: CompanyUserObject, + companyStats?: CompanyStatsObject, +): CompanyObject { + const res: CompanyObject = { + id: companyEntity.id, + name: companyEntity.name || "", + logo: companyEntity.logo || "", + plan: companyEntity.plan, + identity_provider: companyEntity.identity_provider, + identity_provider_id: companyEntity.identity_provider_id, + }; + + if (companyUserObject) { + res.status = "active"; // FIXME: Deactivated console user are removed from company on twake side + res.role = companyUserObject.role; + } + + if (companyStats) { + res.stats = companyStats; + } + + res.plan = { + name: res.plan?.name || "free", + limits: res.plan?.limits || {}, + features: res.plan?.features || {}, + }; + + res.plan.limits = Object.assign( + { + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]: 10000, + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]: -1, + }, + res.plan?.limits || {}, + ); + + res.plan.features = Object.assign( + { + [CompanyFeaturesEnum.CHAT_GUESTS]: true, + [CompanyFeaturesEnum.CHAT_MESSAGE_HISTORY]: true, + [CompanyFeaturesEnum.CHAT_MULTIPLE_WORKSPACES]: true, + [CompanyFeaturesEnum.CHAT_EDIT_FILES]: true, + [CompanyFeaturesEnum.CHAT_UNLIMITED_STORAGE]: true, + [CompanyFeaturesEnum.COMPANY_INVITE_MEMBER]: true, + }, + { + ...(res.plan?.features || {}), + [CompanyFeaturesEnum.COMPANY_INVITE_MEMBER]: + res.plan?.limits[CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT] <= 0 || + res.stats.total_members < res.plan?.limits[CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT], + }, + ); + + return res; +} + +export function getCompanyStats(company: Company, total_messages: number = 0): CompanyStatsObject { + return { + created_at: company.dateAdded, + total_members: company.stats?.total_members || 0, + total_guests: company.stats?.total_guests || 0, + total_messages, + }; +} diff --git a/twake/backend/node/src/services/user/web/controller.ts b/twake/backend/node/src/services/user/web/controller.ts index f87b671317..eac193467c 100644 --- a/twake/backend/node/src/services/user/web/controller.ts +++ b/twake/backend/node/src/services/user/web/controller.ts @@ -1,10 +1,11 @@ import { FastifyReply, FastifyRequest } from "fastify"; import { - CrudExeption, + CrudException, ExecutionContext, ListResult, Pagination, } from "../../../core/platform/framework/api/crud-service"; +import { uniq, orderBy } from "lodash"; import { CrudController } from "../../../core/platform/services/webserver/types"; import { @@ -13,7 +14,6 @@ import { ResourceGetResponse, ResourceListResponse, } from "../../../utils/types"; -import UserServiceAPI from "../api"; import User from "../entities/user"; import { @@ -30,9 +30,13 @@ import { } from "./types"; import Company from "../entities/company"; import CompanyUser from "../entities/company_user"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; import coalesce from "../../../utils/coalesce"; import { getCompanyRooms, getUserRooms } from "../realtime"; +import { formatCompany, getCompanyStats } from "../utils"; +import { formatUser } from "../../../utils/users"; +import gr from "../../global-resolver"; +import { UserChannel, UsersIncludedChannel } from "../../channels/entities"; +import { ChannelObject } from "../../channels/services/channel/types"; export class UsersCrudController implements @@ -43,8 +47,6 @@ export class UsersCrudController ResourceDeleteResponse > { - constructor(protected realtime: RealtimeServiceAPI, protected service: UserServiceAPI) {} - async get( request: FastifyRequest<{ Params: UserParameters }>, reply: FastifyReply, @@ -56,20 +58,20 @@ export class UsersCrudController id = context.user.id; } - const user = await this.service.users.get({ id: id }, getExecutionContext(request)); + const user = await gr.services.users.get({ id: id }); if (!user) { - throw CrudExeption.notFound(`User ${id} not found`); + throw CrudException.notFound(`User ${id} not found`); } - const userObject = await this.service.formatUser(user, { + const userObject = await formatUser(user, { includeCompanies: context.user.id === id, }); return { resource: userObject, websocket: context.user.id - ? this.realtime.sign(getUserRooms(user), context.user.id)[0] + ? gr.platformServices.realtime.sign(getUserRooms(user), context.user.id)[0] : undefined, }; } @@ -80,10 +82,7 @@ export class UsersCrudController ): Promise> { const context = getExecutionContext(request); - const user = await this.service.users.get( - { id: context.user.id }, - getExecutionContext(request), - ); + const user = await gr.services.users.get({ id: context.user.id }); if (!user) { reply.notFound(`User ${context.user.id} not found`); return; @@ -91,17 +90,17 @@ export class UsersCrudController user.status_icon = coalesce(request.body.resource, user.status_icon); - await this.service.users.save(user, {}, context); + await gr.services.users.save(user, context); return { - resource: await this.service.formatUser(user), + resource: await formatUser(user), }; } async setPreferences( request: FastifyRequest<{ Body: User["preferences"] }>, ): Promise { - const preferences = await this.service.users.setPreferences( + const preferences = await gr.services.users.setPreferences( { id: request.currentUser.id }, request.body, ); @@ -117,7 +116,7 @@ export class UsersCrudController let users: ListResult; if (request.query.search) { - users = await this.service.users.search( + users = await gr.services.users.search( new Pagination(request.query.page_token, request.query.limit), { search: request.query.search, @@ -126,7 +125,7 @@ export class UsersCrudController context, ); } else { - users = await this.service.users.list( + users = await gr.services.users.list( new Pagination(request.query.page_token, request.query.limit), { userIds }, context, @@ -135,7 +134,7 @@ export class UsersCrudController const resUsers = await Promise.all( users.getEntities().map(user => - this.service.formatUser(user, { + formatUser(user, { includeCompanies: request.query.include_companies, }), ), @@ -144,7 +143,7 @@ export class UsersCrudController // return users; return { resources: resUsers, - websockets: this.realtime.sign([], context.user.id), // empty for now + websockets: gr.platformServices.realtime.sign([], context.user.id), // empty for now }; } @@ -154,15 +153,15 @@ export class UsersCrudController ): Promise> { const context = getExecutionContext(request); - const user = await this.service.users.get({ id: request.params.id }, context); + const user = await gr.services.users.get({ id: request.params.id }); if (!user) { - throw CrudExeption.notFound(`User ${request.params.id} not found`); + throw CrudException.notFound(`User ${request.params.id} not found`); } const [currentUserCompanies, requestedUserCompanies] = await Promise.all( [context.user.id, request.params.id].map(userId => - this.service.users.getUserCompanies({ id: userId }), + gr.services.users.getUserCompanies({ id: userId }), ), ); @@ -172,7 +171,7 @@ export class UsersCrudController const retrieveCompanyCached = async (companyId: string): Promise => { const company = companiesCache.get(companyId) || - (await this.service.companies.getCompany({ id: companyId })); + (await gr.services.companies.getCompany({ id: companyId })); companiesCache.set(companyId, company); return company; }; @@ -184,14 +183,14 @@ export class UsersCrudController retrieveCompanyCached(uc.group_id).then(async (c: Company) => [ c, uc, - await this.getCompanyStats(c), + getCompanyStats(c, await gr.services.statistics.get(c.id, "messages")), ]), ), )) as [Company, CompanyUserObject, CompanyStatsObject][]; return { - resources: combos.map(combo => this.service.formatCompany(...combo)), - websockets: this.realtime.sign([], context.user.id), + resources: combos.map(combo => formatCompany(...combo)), + websockets: gr.platformServices.realtime.sign([], context.user.id), }; } @@ -199,16 +198,16 @@ export class UsersCrudController request: FastifyRequest<{ Params: CompanyParameters }>, reply: FastifyReply, ): Promise> { - const company = await this.service.companies.getCompany({ id: request.params.id }); + const company = await gr.services.companies.getCompany({ id: request.params.id }); const context = getExecutionContext(request); if (!company) { - throw CrudExeption.notFound(`Company ${request.params.id} not found`); + throw CrudException.notFound(`Company ${request.params.id} not found`); } let companyUserObj: CompanyUserObject | null = null; if (context?.user?.id) { - const companyUser = await this.service.companies.getCompanyUser(company, { + const companyUser = await gr.services.companies.getCompanyUser(company, { id: context.user.id, }); companyUserObj = { @@ -219,37 +218,28 @@ export class UsersCrudController } return { - resource: this.service.formatCompany( + resource: formatCompany( company, companyUserObj, - await this.getCompanyStats(company), + getCompanyStats(company, await gr.services.statistics.get(company.id, "messages")), ), websocket: context.user?.id - ? this.realtime.sign(getCompanyRooms(company), context.user.id)[0] + ? gr.platformServices.realtime.sign(getCompanyRooms(company), context.user.id)[0] : undefined, }; } - private async getCompanyStats(company: Company): Promise { - return { - created_at: company.dateAdded, - total_members: company.stats?.total_members || 0, - total_guests: company.stats?.total_guests || 0, - total_messages: await this.service.statistics.get(company.id, "messages"), - }; - } - async registerUserDevice( request: FastifyRequest<{ Body: RegisterDeviceBody }>, reply: FastifyReply, ): Promise> { const resource = request.body.resource; if (resource.type !== "FCM") { - throw CrudExeption.badRequest("Type should be FCM only"); + throw CrudException.badRequest("Type should be FCM only"); } const context = getExecutionContext(request); - await this.service.users.registerUserDevice( + await gr.services.users.registerUserDevice( { id: context.user.id }, resource.value, resource.type, @@ -267,7 +257,7 @@ export class UsersCrudController ): Promise> { const context = getExecutionContext(request); - const userDevices = await this.service.users.getUserDevices({ id: context.user.id }); + const userDevices = await gr.services.users.getUserDevices({ id: context.user.id }); return { resources: userDevices.map( @@ -281,16 +271,53 @@ export class UsersCrudController reply: FastifyReply, ): Promise { const context = getExecutionContext(request); - const userDevices = await this.service.users.getUserDevices({ id: context.user.id }); + const userDevices = await gr.services.users.getUserDevices({ id: context.user.id }); const device = await userDevices.find(ud => ud.id == request.params.value); if (device) { - await this.service.users.deregisterUserDevice(device.id); + await gr.services.users.deregisterUserDevice(device.id); } reply.status(204); return { status: "success", }; } + + async recent( + request: FastifyRequest<{ Params: CompanyParameters; Querystring: { limit: 100 } }>, + reply: FastifyReply, + ): Promise> { + const context = getExecutionContext(request); + const userId = context.user.id; + const companyId = request.params.id; + + let channels: UserChannel[] = await gr.services.channels.channels + .getChannelsForUsersInWorkspace(companyId, "direct", userId, undefined, context) + .then(list => list.getEntities()); + + channels = channels.sort((a, b) => b.last_activity - a.last_activity); + channels = channels.slice(0, 100); + + const userIncludedChannels: UsersIncludedChannel[] = await Promise.all( + channels.map( + channel => + gr.services.channels.channels.includeUsersInDirectChannel( + channel, + userId, + ) as Promise, + ), + ); + + const users: UserObject[] = []; + for (const channel of userIncludedChannels) { + for (const user of channel.users) { + if (user.id != request.currentUser.id) users.push(user); + } + } + + return { + resources: [...uniq(users).slice(0, request.query.limit)], + }; + } } function getExecutionContext(request: FastifyRequest): ExecutionContext { diff --git a/twake/backend/node/src/services/user/web/index.ts b/twake/backend/node/src/services/user/web/index.ts index e602946e15..f83ffff2cd 100644 --- a/twake/backend/node/src/services/user/web/index.ts +++ b/twake/backend/node/src/services/user/web/index.ts @@ -1,14 +1,11 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import UserServiceAPI from "../api"; + import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: UserServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /users routes"); diff --git a/twake/backend/node/src/services/user/web/routes.ts b/twake/backend/node/src/services/user/web/routes.ts index dd8bd7bbde..5a288de908 100644 --- a/twake/backend/node/src/services/user/web/routes.ts +++ b/twake/backend/node/src/services/user/web/routes.ts @@ -1,6 +1,5 @@ import { FastifyInstance, FastifyPluginCallback, FastifyRequest } from "fastify"; import { UsersCrudController } from "./controller"; -import UserServiceAPI from "../api"; import { deleteDeviceSchema, getCompanySchema, @@ -11,15 +10,11 @@ import { postDevicesSchema, setUserPreferencesSchema, } from "./schemas"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; const usersUrl = "/users"; -const routes: FastifyPluginCallback<{ - service: UserServiceAPI; - realtime: RealtimeServiceAPI; -}> = (fastify: FastifyInstance, options, next) => { - const usersController = new UsersCrudController(options.realtime, options.service); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const usersController = new UsersCrudController(); const accessControl = async (request: FastifyRequest) => { // TODO const authorized = true; @@ -39,7 +34,7 @@ const routes: FastifyPluginCallback<{ }); fastify.route({ - method: "GET", + method: "POST", url: `${usersUrl}/me/preferences`, preHandler: accessControl, preValidation: [fastify.authenticate], @@ -71,7 +66,7 @@ const routes: FastifyPluginCallback<{ url: `${usersUrl}/:id/companies`, preHandler: accessControl, preValidation: [fastify.authenticate], - //schema: getUserCompaniesSchema, //Fixme currently not working because we don't know features in advances and so it doesn't pass + schema: getUserCompaniesSchema, //Fixme currently not working because we don't know features in advances and so it doesn't pass handler: usersController.getUserCompanies.bind(usersController), }); @@ -80,7 +75,7 @@ const routes: FastifyPluginCallback<{ method: "GET", url: "/companies/:id", preValidation: [fastify.authenticateOptional], - //schema: getCompanySchema, //Fixme currently not working because we don't know features in advances and so it doesn't pass + schema: getCompanySchema, //Fixme currently not working because we don't know features in advances and so it doesn't pass handler: usersController.getCompany.bind(usersController), }); @@ -111,6 +106,14 @@ const routes: FastifyPluginCallback<{ handler: usersController.deregisterUserDevice.bind(usersController), }); + // recent users the current user has interacted with + fastify.route({ + method: "GET", + url: "/companies/:id/users/recent", + preValidation: [fastify.authenticateOptional], + handler: usersController.recent.bind(usersController), + }); + next(); }; diff --git a/twake/backend/node/src/services/user/web/schemas.ts b/twake/backend/node/src/services/user/web/schemas.ts index b075736b2c..6f33289a79 100644 --- a/twake/backend/node/src/services/user/web/schemas.ts +++ b/twake/backend/node/src/services/user/web/schemas.ts @@ -1,4 +1,5 @@ import { webSocketSchema } from "../../../utils/types"; +import { CompanyFeaturesEnum, CompanyLimitsEnum } from "./types"; export const userObjectSchema = { type: "object", @@ -19,16 +20,28 @@ export const userObjectSchema = { status: { type: "string" }, last_activity: { type: "number" }, - //Below is only if this is myself - - preference: { + // cache: { type: ["object", "null"] }, + cache: { type: "object", properties: { - locale: { type: "string" }, - timezone: { type: "number" }, + companies: { type: ["array", "null"] }, }, }, + //Below is only if this is myself + preferences: { + type: "object", + properties: { + tutorial_done: { type: ["boolean", "null"] }, + channel_ordering: { type: ["string", "null"] }, + recent_workspaces: { type: ["array", "null"] }, + knowledge_graph: { type: ["string", "null"] }, + locale: { type: ["string", "null"] }, + timezone: { type: ["number", "null"] }, + language: { type: ["string", "null"] }, + allow_tracking: { type: ["boolean", "null"] }, + }, + }, companies: { type: "array", items: { @@ -47,10 +60,12 @@ export const userObjectSchema = { }, }, }, + // TODO this is temporary, should be deleted + preference: {}, }, }; -const companyObjectSchema = { +export const companyObjectSchema = { type: "object", properties: { id: { type: "string" }, @@ -60,8 +75,27 @@ const companyObjectSchema = { type: ["object", "null"], properties: { name: { type: "string" }, + limits: { + type: ["object", "null"], + properties: { + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]: { type: "number" }, + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]: { type: "number" }, + }, + }, features: { type: "object", + properties: { + [CompanyFeaturesEnum.CHAT_EDIT_FILES]: { type: ["boolean"] }, + [CompanyFeaturesEnum.CHAT_GUESTS]: { type: ["boolean"] }, + [CompanyFeaturesEnum.CHAT_MESSAGE_HISTORY]: { type: "boolean" }, + [CompanyFeaturesEnum.CHAT_MULTIPLE_WORKSPACES]: { type: "boolean" }, + [CompanyFeaturesEnum.CHAT_UNLIMITED_STORAGE]: { type: "boolean" }, + [CompanyFeaturesEnum.COMPANY_INVITE_MEMBER]: { type: "boolean" }, + guests: { type: "number" }, // to rename or delete + members: { type: "number" }, // to rename or delete + storage: { type: "number" }, // to rename or delete + }, + required: [] as string[], }, }, }, @@ -97,14 +131,19 @@ export const getUserSchema = { export const setUserPreferencesSchema = { request: { properties: { - tutorial_done: { type: "boolean" }, - channel_ordering: { type: "string" }, + tutorial_done: { type: ["boolean", "null"] }, + channel_ordering: { type: ["string", "null"] }, + recent_workspaces: { type: ["array", "null"] }, + knowledge_graph: { type: ["string", "null"] }, + locale: { type: ["string", "null"] }, + timezone: { type: ["number", "null"] }, + language: { type: ["string", "null"] }, + allow_tracking: { type: ["boolean", "null"] }, }, + required: [] as any[], }, response: { - "2xx": { - type: "object", - }, + "2xx": userObjectSchema.properties.preferences, }, }; diff --git a/twake/backend/node/src/services/user/web/types.ts b/twake/backend/node/src/services/user/web/types.ts index d58f2d899d..6c23ea05a2 100644 --- a/twake/backend/node/src/services/user/web/types.ts +++ b/twake/backend/node/src/services/user/web/types.ts @@ -1,5 +1,5 @@ import { PaginationQueryParameters } from "../../../utils/types"; -import { ChannelMember } from "../../channels/entities"; +import User from "../entities/user"; export interface UserListQueryParameters extends PaginationQueryParameters { user_ids?: string; @@ -53,21 +53,50 @@ export interface UserObject { deleted: boolean; status: string; //Single string for the status last_activity: number; + last_seen?: number; + is_connected?: boolean; + cache: { companies: string[] }; //Below is only if this is myself + preferences?: User["preferences"]; + companies?: CompanyUserObject[]; - preference?: { - locale: string; - timezone: number; - allow_tracking: boolean; - }; + // TODO this is temporary, should be deleted + preference?: User["preferences"]; +} - companies?: CompanyUserObject[]; +export enum CompanyLimitsEnum { + CHAT_MESSAGE_HISTORY_LIMIT = "chat:message_history_limit", + COMPANY_MEMBERS_LIMIT = "company:members_limit", // 100 } +export enum CompanyFeaturesEnum { + CHAT_GUESTS = "chat:guests", + CHAT_MESSAGE_HISTORY = "chat:message_history", + CHAT_MULTIPLE_WORKSPACES = "chat:multiple_workspaces", + CHAT_EDIT_FILES = "chat:edit_files", + CHAT_UNLIMITED_STORAGE = "chat:unlimited_storage", + COMPANY_INVITE_MEMBER = "company:invite_member", +} + +export type CompanyFeaturesObject = { + [CompanyFeaturesEnum.CHAT_GUESTS]?: boolean; + [CompanyFeaturesEnum.CHAT_MESSAGE_HISTORY]?: boolean; + [CompanyFeaturesEnum.CHAT_MULTIPLE_WORKSPACES]?: boolean; + [CompanyFeaturesEnum.CHAT_EDIT_FILES]?: boolean; + [CompanyFeaturesEnum.CHAT_UNLIMITED_STORAGE]?: boolean; + [CompanyFeaturesEnum.COMPANY_INVITE_MEMBER]?: boolean; +}; + +export type CompanyLimitsObject = { + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]?: number; + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]?: number; +}; + export interface CompanyPlanObject { name: string; - features: any; + limits?: CompanyLimitsObject; + features?: CompanyFeaturesObject; } export interface CompanyStatsObject { diff --git a/twake/backend/node/src/services/workspaces/api.ts b/twake/backend/node/src/services/workspaces/api.ts deleted file mode 100644 index 86779cba3e..0000000000 --- a/twake/backend/node/src/services/workspaces/api.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { Initializable, TwakeServiceProvider } from "../../core/platform/framework"; -import { - CRUDService, - DeleteResult, - ExecutionContext, - ListResult, - Paginable, -} from "../../core/platform/framework/api/crud-service"; -import Workspace, { WorkspacePrimaryKey } from "./entities/workspace"; -import { CompaniesServiceAPI, UsersServiceAPI } from "../user/api"; -import WorkspaceUser, { WorkspaceUserPrimaryKey } from "../workspaces/entities/workspace_user"; -import { Observable } from "rxjs"; -import User, { UserPrimaryKey } from "../user/entities/user"; -import { WorkspaceUserRole } from "./types"; -import { CompanyPrimaryKey } from "../user/entities/company"; -import WorkspacePendingUser, { - WorkspacePendingUserPrimaryKey, -} from "./entities/workspace_pending_users"; -import { CompanyUserRole } from "../user/web/types"; -import { uuid } from "../../utils/types"; -import { ConsoleServiceAPI } from "../console/api"; -import { WorkspaceInviteTokenObject } from "./web/types"; -import WorkspaceInviteTokens from "./entities/workspace_invite_tokens"; -import { Readable } from "stream"; - -export default interface WorkspaceServicesAPI extends TwakeServiceProvider, Initializable { - workspaces: WorkspaceServiceAPI; - companies: CompaniesServiceAPI; - users: UsersServiceAPI; - console: ConsoleServiceAPI; -} - -export interface WorkspaceServiceAPI - extends TwakeServiceProvider, - Initializable, - CRUDService { - addUser( - workspacePk: WorkspacePrimaryKey, - userPk: UserPrimaryKey, - role: WorkspaceUserRole, - ): Promise; - - updateUserRole(workspaceUserPk: WorkspaceUserPrimaryKey, role: WorkspaceUserRole): Promise; - - getAllForCompany(companyId: uuid): Promise; - - getUsersCount(workspaceId: string): Promise; - - processPendingUser(user: User): Promise; - - thumbnail(workspaceId: string): Promise<{ file: Readable }>; - - removeUser( - workspaceUserPk: WorkspaceUserPrimaryKey, - ): Promise>; - - /** - * Get workspace users in the given workspace - * - * @param workspaceId - * @param pagination - */ - getUsers( - workspaceId: Pick, - pagination?: Paginable, - ): Promise>; - - /** - * Get workspace user in the given workspace - * - * @param workspaceId - * @param userId - */ - getUser( - workspaceUserPk: Pick, - ): Promise; - - /** - * Get all the workspace for a user - * - * @param userId - * @param userId - */ - getAllForUser( - userId: Pick, - companyId: CompanyPrimaryKey, - ): Promise; - - /** - * Get all the users of a workspace as Observable - * - * @param workspaceId - */ - getAllUsers$( - workspaceId: Pick, - ): Observable; - - /** - * Paginate over all the users of a workspace - * - * @param workspaceId - * @param pagination - */ - getAllUsers$( - workspaceId: Pick, - pagination: Paginable, - ): Observable; - - addPendingUser( - workspacePk: WorkspacePendingUserPrimaryKey, - workspaceRole: WorkspaceUserRole, - companyRole: CompanyUserRole, - ): Promise; - - getPendingUser(primaryKey: WorkspacePendingUserPrimaryKey): Promise; - - getPendingUsers( - workspaceId: Pick, - ): Promise; - - removePendingUser( - workspaceUserPk: WorkspacePendingUserPrimaryKey, - ): Promise>; - - getInviteToken(companyId: string, workspaceId: string): Promise; - createInviteToken(companyId: string, workspaceId: string): Promise; - deleteInviteToken(companyId: string, workspaceId: string): Promise; - getInviteTokenInfo(jwtToken: string): Promise; -} diff --git a/twake/backend/node/src/services/workspaces/entities/workspace_invite_tokens.ts b/twake/backend/node/src/services/workspaces/entities/workspace_invite_tokens.ts index 881fd39674..a7565d24d3 100644 --- a/twake/backend/node/src/services/workspaces/entities/workspace_invite_tokens.ts +++ b/twake/backend/node/src/services/workspaces/entities/workspace_invite_tokens.ts @@ -4,7 +4,7 @@ import { Column, Entity } from "../../../core/platform/services/database/service export const TYPE = "workspace_invite_tokens"; @Entity(TYPE, { - primaryKey: [["company_id"], "workspace_id", "invite_token"], + primaryKey: [["company_id"], "workspace_id", "user_id", "invite_token"], type: TYPE, }) export default class WorkspaceInviteTokens { @@ -14,13 +14,16 @@ export default class WorkspaceInviteTokens { @Column("workspace_id", "string") workspace_id: string; + @Column("user_id", "string") + user_id: string; + @Column("invite_token", "string") invite_token: string; } export type WorkspaceInviteTokensPrimaryKey = Pick< WorkspaceInviteTokens, - "company_id" | "workspace_id" | "invite_token" + "company_id" | "workspace_id" | "user_id" | "invite_token" >; export function getInstance( diff --git a/twake/backend/node/src/services/workspaces/entities/workspace_user.ts b/twake/backend/node/src/services/workspaces/entities/workspace_user.ts index 064f408ce6..49144725c4 100644 --- a/twake/backend/node/src/services/workspaces/entities/workspace_user.ts +++ b/twake/backend/node/src/services/workspaces/entities/workspace_user.ts @@ -22,7 +22,7 @@ export default class WorkspaceUser { id: string; @Column("role", "string") - role: WorkspaceUserRole; //Relative to workspace only (not relative to company) + role: WorkspaceUserRole = "member"; //Relative to workspace only (not relative to company) @Column("date_added", "number") dateAdded: number; @@ -41,3 +41,9 @@ export function getInstance( ): WorkspaceUser { return merge(new WorkspaceUser(), workspaceUser); } + +export function formatWorkspaceUser(workspaceUser: WorkspaceUser): WorkspaceUser { + if (!workspaceUser) return workspaceUser; + workspaceUser.role = workspaceUser.role || "member"; + return workspaceUser; +} diff --git a/twake/backend/node/src/services/workspaces/index.ts b/twake/backend/node/src/services/workspaces/index.ts index f544f63813..4b940982fe 100644 --- a/twake/backend/node/src/services/workspaces/index.ts +++ b/twake/backend/node/src/services/workspaces/index.ts @@ -1,43 +1,23 @@ -import { Consumes, Prefix, TwakeService } from "../../core/platform/framework"; -import WorkspaceServiceAPI from "./api"; -import web from "./web/index"; -import { getService } from "./services"; -import { ConsoleServiceAPI } from "../console/api"; -import { PlatformServicesAPI } from "../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../applications/api"; -import AuthServiceAPI from "../../core/platform/services/auth/provider"; -import { RealtimeServiceAPI } from "../../core/platform/services/realtime/api"; -import UserServiceAPI from "../user/api"; +import { Prefix, TwakeService } from "../../core/platform/framework"; +import WebServerAPI from "../../core/platform/services/webserver/provider"; +import web from "./web"; +import { WorkspaceServiceImpl } from "./services/workspace"; @Prefix("/internal/services/workspaces/v1") -@Consumes(["platform-services", "console", "applications", "auth", "realtime"]) -export default class WorkspaceService extends TwakeService { +export default class Service extends TwakeService { version = "1"; name = "workspaces"; - private service: WorkspaceServiceAPI; public async doInit(): Promise { - const platformServices = this.context.getProvider("platform-services"); - - const fastify = platformServices.fastify.getServer(); - const console = this.context.getProvider("console"); - const applications = this.context.getProvider("applications"); - const auth = this.context.getProvider("auth"); - const realtime = this.context.getProvider("realtime"); - const users = this.context.getProvider("user"); - - this.service = getService(platformServices, console, applications, auth, users); - await this.service?.init(this.context); - + const fastify = this.context.getProvider("webserver").getServer(); fastify.register((instance, _opts, next) => { - web(instance, { prefix: this.prefix, service: this.service, realtime }); + web(instance, { prefix: this.prefix }); next(); }); - return this; } - api(): WorkspaceServiceAPI { - return this.service; + api(): WorkspaceServiceImpl { + return null; } } diff --git a/twake/backend/node/src/services/workspaces/services/index.ts b/twake/backend/node/src/services/workspaces/services/index.ts deleted file mode 100644 index 4a041c9dc1..0000000000 --- a/twake/backend/node/src/services/workspaces/services/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { TwakeContext } from "../../../core/platform/framework"; -import WorkspaceServicesAPI, { WorkspaceServiceAPI } from "../api"; -import { getService as getWorkspaceService } from "./workspace"; -import { getService as getCompaniesService } from "../../user/services/companies"; -import { getService as getUsersService } from "../../user/services/users"; -import UserServiceAPI, { CompaniesServiceAPI, UsersServiceAPI } from "../../user/api"; -import { ConsoleServiceAPI } from "../../console/api"; -import { PlatformServicesAPI } from "../../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../../applications/api"; -import AuthServiceAPI from "../../../core/platform/services/auth/provider"; - -export function getService( - platformServices: PlatformServicesAPI, - consoleService: ConsoleServiceAPI, - applicationsService: ApplicationServiceAPI, - auth: AuthServiceAPI, - users: UserServiceAPI, -): WorkspaceServicesAPI { - return new Service(platformServices, consoleService, applicationsService, auth, users); -} - -class Service implements WorkspaceServicesAPI { - version: "1"; - workspaces: WorkspaceServiceAPI; - companies: CompaniesServiceAPI; - users: UsersServiceAPI; - - constructor( - platformServices: PlatformServicesAPI, - readonly console: ConsoleServiceAPI, - readonly applications: ApplicationServiceAPI, - readonly auth: AuthServiceAPI, - protected userService: UserServiceAPI, - ) { - this.companies = this.userService.companies; - this.users = getUsersService(platformServices); - this.workspaces = getWorkspaceService( - platformServices, - this.users, - this.companies, - this.applications, - auth, - ); - } - - async init(context: TwakeContext): Promise { - try { - await Promise.all([ - this.workspaces.init(context), - this.companies.init(context), - this.users.init(context), - ]); - } catch (err) { - console.error("Error while initializing workspace service", err); - } - return this; - } -} diff --git a/twake/backend/node/src/services/workspaces/services/workspace.ts b/twake/backend/node/src/services/workspaces/services/workspace.ts new file mode 100644 index 0000000000..4cd54ff415 --- /dev/null +++ b/twake/backend/node/src/services/workspaces/services/workspace.ts @@ -0,0 +1,776 @@ +import { concat, EMPTY, from, Observable } from "rxjs"; +import { mergeMap } from "rxjs/operators"; +import { + CreateResult, + CrudException, + DeleteResult, + ExecutionContext, + ListResult, + OperationType, + Paginable, + Pagination, + SaveResult, + UpdateResult, +} from "../../../core/platform/framework/api/crud-service"; +import Repository from "../../../core/platform/services/database/services/orm/repository/repository"; +import WorkspaceUser, { + formatWorkspaceUser, + getInstance as getWorkspaceUserInstance, + TYPE as WorkspaceUserType, + WorkspaceUserPrimaryKey, +} from "../../workspaces/entities/workspace_user"; +import Workspace, { + getInstance as getWorkspaceInstance, + TYPE, + TYPE as WorkspaceType, + WorkspacePrimaryKey, +} from "../../workspaces/entities/workspace"; +import { WorkspaceExecutionContext, WorkspaceUserRole } from "../types"; +import User, { UserPrimaryKey } from "../../user/entities/user"; +import { CompanyPrimaryKey } from "../../user/entities/company"; +import _, { merge } from "lodash"; +import WorkspacePendingUser, { + TYPE as WorkspacePendingUserType, + WorkspacePendingUserPrimaryKey, +} from "../entities/workspace_pending_users"; +import { CompanyUserRole } from "../../user/web/types"; +import { ResourceEventsPayload, uuid } from "../../../utils/types"; +import { CounterProvider } from "../../../core/platform/services/counter/provider"; +import { + TYPE as WorkspaceCounterEntityType, + WorkspaceCounterEntity, + WorkspaceCounterPrimaryKey, +} from "../entities/workspace_counters"; +import { countRepositoryItems } from "../../../utils/counters"; +import { + Initializable, + RealtimeSaved, + TwakeServiceProvider, +} from "../../../core/platform/framework"; +import { ResourcePath } from "../../../core/platform/services/realtime/types"; +import { getRoomName, getWorkspacePath } from "../realtime"; +import { InviteTokenObject, WorkspaceInviteTokenObject } from "../web/types"; +import WorkspaceInviteTokens, { + getInstance as getWorkspaceInviteTokensInstance, + TYPE as WorkspaceInviteTokensType, + WorkspaceInviteTokensPrimaryKey, +} from "../entities/workspace_invite_tokens"; +import { randomBytes } from "crypto"; +import { Readable } from "stream"; +import { expandUUID4, reduceUUID4 } from "../../../utils/uuid-reducer"; +import gr from "../../global-resolver"; +import { logger } from "@sentry/utils"; +import { localEventBus } from "../../../core/platform/framework/event-bus"; +import { + KnowledgeGraphEvents, + KnowledgeGraphGenericEventPayload, +} from "../../../core/platform/services/knowledge-graph/types"; + +export class WorkspaceServiceImpl implements TwakeServiceProvider, Initializable { + version: "1"; + private workspaceUserRepository: Repository; + private workspaceRepository: Repository; + private workspacePendingUserRepository: Repository; + private workspaceCounter: CounterProvider; + private workspaceInviteTokensRepository: Repository; + + async init(): Promise { + this.workspaceUserRepository = await gr.database.getRepository( + WorkspaceUserType, + WorkspaceUser, + ); + + this.workspaceRepository = await gr.database.getRepository(WorkspaceType, Workspace); + + const workspaceCountersRepository = await gr.database.getRepository( + WorkspaceCounterEntityType, + WorkspaceCounterEntity, + ); + + this.workspacePendingUserRepository = await gr.database.getRepository( + WorkspacePendingUserType, + WorkspacePendingUser, + ); + + this.workspaceCounter = await gr.platformServices.counter.getCounter( + workspaceCountersRepository, + ); + + this.workspaceCounter.setReviseCallback(async (pk: WorkspaceCounterPrimaryKey) => { + if (pk.counter_type == "members") { + return countRepositoryItems(this.workspaceUserRepository, { workspace_id: pk.id }); + } + return 0; + }); + + this.workspaceInviteTokensRepository = await gr.database.getRepository( + WorkspaceInviteTokensType, + WorkspaceInviteTokens, + ); + + //If user deleted from a company, remove it from all workspace + localEventBus.subscribe("company:user:deleted", async data => { + if (data?.user?.id && data?.company?.id) + gr.services.workspaces.ensureUserNotInCompanyIsNotInWorkspace(data.user, data.company.id); + }); + + return this; + } + + get(pk: WorkspacePrimaryKey, context?: ExecutionContext): Promise { + return this.workspaceRepository.findOne(pk, {}, context); + } + + // TODO: remove logic from context + async create(workspace: Workspace, context?: ExecutionContext): Promise> { + const workspaceToCreate: Workspace = getWorkspaceInstance({ + ...workspace, + ...{ + name: await this.getWorkspaceName(workspace.name, workspace.company_id, workspace.id), + dateAdded: Date.now(), + isDeleted: false, + isArchived: false, + }, + }); + + const userId = context?.user?.id || ""; + + const created = await this.save( + workspaceToCreate, + {}, + { company_id: workspace.company_id, user: { id: userId, server_request: true } }, + ); + + await gr.services.applications.companyApps.initWithDefaultApplications( + created.entity.company_id, + { + company: { id: created.entity.company_id }, + user: { id: userId, server_request: true }, + }, + ); + + return new CreateResult(TYPE, created.entity); + } + + // TODO: remove logic from context + @RealtimeSaved((workspace, context) => [ + { + // FIXME: For now the room is defined at the company level + // It meay be good to have a special room where just some users are receiving this event + room: ResourcePath.get(getRoomName(workspace)), + path: getWorkspacePath(workspace, context as WorkspaceExecutionContext), + }, + ]) + async save( + item: Partial, + options?: SaveOptions & { logo_b64?: string }, + context?: WorkspaceExecutionContext, + ): Promise> { + let workspace = getWorkspaceInstance({ + ...item, + ...{ + company_id: (context.user.server_request ? item.company_id : null) || context.company_id, + name: "", + dateAdded: Date.now(), + isArchived: false, + isDefault: false, + }, + }); + + if (item.id && !context?.user?.server_request) { + // ON UPDATE + workspace = await this.get({ + id: item.id, + company_id: context.company_id, + }); + + if (!workspace) { + throw new Error(`Unable to edit inexistent workspace ${item.id}`); + } + } + + const logoInternalPath = `/workspaces/${workspace.id}/thumbnail.png`; + const logoPublicPath = `/internal/services/workspaces/v1/companies/${ + workspace.company_id + }/workspaces/${workspace.id}/thumbnail?t=${new Date().getTime()}`; + let logoPublicUrl = undefined; + + if (workspace.logo && item.logo === "none") { + if (!options.logo_b64) { + //If options.logo_b64 then we'll just replace the file content + await gr.platformServices.storage.remove(logoInternalPath); + workspace.logo = null; + } + } + + if (options.logo_b64) { + const s = new Readable(); + s.push(Buffer.from(options.logo_b64.split(",").pop(), "base64")); + s.push(null); + await gr.platformServices.storage.write(logoInternalPath, s); + logoPublicUrl = logoPublicPath; + } + + workspace = merge(workspace, { + name: await this.getWorkspaceName(item.name, context.company_id, workspace.id), + isArchived: item.isArchived, + isDefault: item.isDefault, + logo: logoPublicUrl || workspace.logo, + }); + + await this.workspaceRepository.save(workspace, context); + + if (!item.id && context.user.id) { + await this.addUser( + { id: workspace.id, company_id: workspace.company_id }, + { id: context.user.id }, + "moderator", + ); + } + + // On created + if (!item.id) { + gr.platformServices.messageQueue.publish("workspace:added", { + data: { + company_id: workspace.company_id, + workspace_id: workspace.id, + }, + }); + + localEventBus.publish>( + KnowledgeGraphEvents.WORKSPACE_CREATED, + { + id: workspace.id, + resource: workspace, + links: [{ relation: "parent", type: "company", id: workspace.company_id }], + }, + ); + } + + return new SaveResult( + TYPE, + workspace, + item.id ? OperationType.UPDATE : OperationType.CREATE, + ); + } + + async thumbnail(workspaceId: string, context?: ExecutionContext): Promise<{ file: Readable }> { + const logoInternalPath = `/workspaces/${workspaceId}/thumbnail.png`; + const file = await gr.platformServices.storage.read(logoInternalPath, {}, context); + return { file }; + } + + async delete( + pk: WorkspacePrimaryKey, + context?: ExecutionContext, + ): Promise> { + const primaryKey: Workspace = merge(new Workspace(), pk); + await this.workspaceRepository.remove(primaryKey, context); + return new DeleteResult(TYPE, primaryKey, true); + } + + // TODO: remove logic from context + list( + pagination: Pagination, + options?: ListOptions, + context?: WorkspaceExecutionContext, + ): Promise> { + const pk = { company_id: context.company_id }; + + return this.workspaceRepository.find(pk, { pagination }, context); + } + + async getAllForCompany(companyId: uuid, context?: ExecutionContext): Promise { + let allCompanyWorkspaces: Workspace[] = []; + let nextPage: Pagination = new Pagination("", "100"); + do { + const tmp = await this.workspaceRepository.find( + { company_id: companyId }, + { pagination: nextPage }, + context, + ); + nextPage = tmp.nextPage as Pagination; + allCompanyWorkspaces = [...allCompanyWorkspaces, ...tmp.getEntities()]; + } while (nextPage.page_token); + + //Check there is at least one workspace in this company or enforce one + if (allCompanyWorkspaces.length == 0) { + const created = await this.create( + getWorkspaceInstance({ + company_id: companyId, + name: "Home", + isDefault: true, + }), + ); + allCompanyWorkspaces.push(created.entity); + } + + return allCompanyWorkspaces; + } + + async addUser( + workspacePk: WorkspacePrimaryKey, + userPk: UserPrimaryKey, + role: WorkspaceUserRole, + context?: ExecutionContext, + ): Promise { + const wurPk = { + workspaceId: workspacePk.id, + userId: userPk.id, + }; + + const alreadyExists = await this.getUser(wurPk); + if (!alreadyExists) { + await this.userCounterIncrease(workspacePk.id, 1); + } + + await this.workspaceUserRepository.save( + getWorkspaceUserInstance({ + workspaceId: workspacePk.id, + userId: userPk.id, + role: role, + }), + context, + ); + + await gr.platformServices.messageQueue.publish( + "workspace:member:added", + { + data: { + company_id: workspacePk.company_id, + workspace_id: workspacePk.id, + user_id: userPk.id, + }, + }, + context, + ); + } + + async updateUserRole( + workspaceUserPk: WorkspaceUserPrimaryKey, + role: WorkspaceUserRole, + context?: ExecutionContext, + ): Promise { + const workspaceUser = await this.getUser(workspaceUserPk); + if (!workspaceUser) { + throw CrudException.notFound("WorkspaceUser entity not found"); + } + await this.workspaceUserRepository.save(merge(workspaceUser, { role }), context); + } + + async checkWorkspaceHasOtherAdmin(workspaceUserPk: WorkspaceUserPrimaryKey): Promise { + //TODO: not implemented, we should check there is still an admin in the workspace before removal. + // Note: company admin and owner are always workspace admins. + return true; + } + + async removeUser( + workspaceUserPk: WorkspaceUserPrimaryKey, + companyId: string, + context?: ExecutionContext, + ): Promise> { + const entity = await this.getUser(workspaceUserPk); + + if (!entity) { + throw CrudException.notFound("WorkspaceUser entity not found"); + } + + if (!(await this.checkWorkspaceHasOtherAdmin(workspaceUserPk))) { + throw CrudException.notFound("No other admin found in workspace"); + } + + await this.workspaceUserRepository.remove(entity, context); + await this.userCounterIncrease(workspaceUserPk.workspaceId, -1, context); + + localEventBus.publish( + "workspace:user:deleted", + { + user: entity, + workspace: { id: workspaceUserPk.workspaceId, company_id: companyId }, + }, + context, + ); + + return new DeleteResult(WorkspaceUserType, workspaceUserPk, true); + } + + async getUsers( + workspaceId: Pick, + pagination?: Paginable, + context?: ExecutionContext, + ): Promise> { + const list = await this.workspaceUserRepository.find( + { workspace_id: workspaceId.workspaceId }, + { pagination: { limitStr: pagination?.limitStr, page_token: pagination?.page_token } }, + context, + ); + list.mapEntities(m => formatWorkspaceUser(m) as any); + return list; + } + + async getUser( + workspaceUserPk: Pick, + context?: ExecutionContext, + ): Promise { + return formatWorkspaceUser( + await this.workspaceUserRepository.findOne( + { + workspace_id: workspaceUserPk.workspaceId, + user_id: workspaceUserPk.userId, + }, + {}, + context, + ), + ); + } + + async processPendingUser( + user: User, + companyId?: string, + context?: ExecutionContext, + ): Promise { + let userCompanies = []; + if (!companyId) { + userCompanies = await gr.services.companies.getAllForUser(user.id); + } else { + userCompanies = [ + await gr.services.companies.getCompanyUser({ id: companyId }, { id: user.id }), + ]; + } + for (const userCompany of userCompanies) { + const workspaces = await this.getAllForCompany(userCompany.group_id); + for (const workspace of workspaces) { + const pendingUserPk = { + workspace_id: workspace.id, + email: user.email_canonical, + }; + const pendingUser = await this.getPendingUser(pendingUserPk); + + if (pendingUser) { + await this.removePendingUser(pendingUserPk); + await this.addUser( + { id: workspace.id, company_id: workspace.company_id }, + { id: user.id }, + pendingUser.role, + ); + } + } + } + } + + async getAllForUser( + userId: Pick, + companyId: CompanyPrimaryKey, + context?: ExecutionContext, + ): Promise { + //Process pending invitation to workspace for this user + const user = await gr.services.users.get({ id: userId.userId }); + await this.processPendingUser(user, companyId?.id); + + //Get all workspaces for this user + const allCompanyWorkspaces = await this.getAllForCompany(companyId.id, context); + const userWorkspaces = ( + await Promise.all( + allCompanyWorkspaces.map(workspace => + this.workspaceUserRepository.findOne( + { + user_id: userId.userId, + workspace_id: workspace.id, + }, + {}, + context, + ), + ), + ) + ) + .map(m => formatWorkspaceUser(m)) + .filter(uw => uw); + + //If user is in no workspace, then it must be invited in the default workspaces, expect if he's guest + if (userWorkspaces.length === 0) { + for (const workspace of allCompanyWorkspaces) { + if (workspace.isDefault && !workspace.isArchived && !workspace.isDeleted) { + try { + //Role will match the company role in the default workspaces + const companyRole = await gr.services.companies.getCompanyUser( + { id: companyId.id }, + { id: userId.userId }, + context, + ); + let role: WorkspaceUserRole = "member"; + if (companyRole.role == "admin" || companyRole.role == "owner") role = "moderator"; + + if (companyRole.role !== "guest") { + await this.addUser(workspace, { id: userId.userId }, role, context); + const uw = formatWorkspaceUser( + await this.workspaceUserRepository.findOne( + { + user_id: userId.userId, + workspace_id: workspace.id, + }, + {}, + context, + ), + ); + if (uw) { + userWorkspaces.push(uw); + } + } + } catch (err) { + console.log(err); + } + } + } + } + + return userWorkspaces; + } + + getAllUsers$( + workspaceId: Pick, + pagination?: Paginable, + ): Observable { + return from(this.getUsers(workspaceId, pagination)).pipe( + mergeMap(workspaceUsers => { + const items$ = from(workspaceUsers.getEntities()); + const next$ = workspaceUsers?.nextPage?.page_token + ? this.getAllUsers$(workspaceId, workspaceUsers.nextPage) + : EMPTY; + + return concat(items$, next$); + }), + ); + } + + async addPendingUser( + primaryKey: WorkspacePendingUserPrimaryKey, + workspaceRole: WorkspaceUserRole, + companyRole: CompanyUserRole, + context?: ExecutionContext, + ): Promise { + if (await this.getPendingUser(primaryKey)) { + throw CrudException.badRequest("User is pending already"); + } + const workspacePendingUser = merge(new WorkspacePendingUser(), { + workspace_id: primaryKey.workspace_id, + email: primaryKey.email, + role: workspaceRole, + company_role: companyRole, + }); + await this.workspacePendingUserRepository.save(workspacePendingUser, context); + } + + getPendingUser( + primaryKey: WorkspacePendingUserPrimaryKey, + context?: ExecutionContext, + ): Promise { + return this.workspacePendingUserRepository.findOne(primaryKey, {}, context); + } + + async getPendingUsers( + primaryKey: Pick, + context?: ExecutionContext, + ): Promise { + return this.workspacePendingUserRepository + .find(primaryKey, {}, context) + .then(a => a.getEntities()); + } + + async removePendingUser( + primaryKey: WorkspacePendingUserPrimaryKey, + context?: ExecutionContext, + ): Promise> { + const pendingUser = await this.getPendingUser(primaryKey); + if (!pendingUser) { + throw CrudException.notFound("Pending user not found"); + } + await this.workspacePendingUserRepository.remove(pendingUser, context); + return new DeleteResult(WorkspacePendingUserType, primaryKey, true); + } + + /** + * @name GetWorkspaceName + * @param exceptedName workspace name that user excepted to have + * @param companyId company that user excepted to create or update the workspace + * @param workspaceId + * @param context + * @returns if workspace name is already used in the company, this will return the exceptedName with the current duplicates number otherwise simply return the exceptedName + */ + private async getWorkspaceName( + exceptedName: string, + companyId: string, + workspaceId: string, + context?: ExecutionContext, + ) { + const workspacesList = await this.list( + null, + {}, + { company_id: companyId, user: { id: null, server_request: true } }, + ); + + workspacesList.filterEntities( + entity => entity.id !== workspaceId && _.includes(entity.name, exceptedName), + ); + + const shouldRenameWorkspace = !workspacesList.isEmpty(); + const duplicatesCount = workspacesList.getEntities().length; + + return shouldRenameWorkspace ? `${exceptedName}(${duplicatesCount + 1})` : exceptedName; + } + + private wsCountPk = (id: string) => ({ id, counter_type: "members" }); + + private userCounterIncrease( + workspaceId: string, + increaseValue: number, + context?: ExecutionContext, + ) { + return this.workspaceCounter.increase(this.wsCountPk(workspaceId), increaseValue, context); + } + + getUsersCount(workspaceId: string, context?: ExecutionContext): Promise { + return this.workspaceCounter.get(this.wsCountPk(workspaceId), context); + } + + async getInviteToken( + companyId: string, + workspaceId: string, + userId: string, + context?: ExecutionContext, + ): Promise { + const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId }; + const res = await this.workspaceInviteTokensRepository.findOne(pk, {}, context); + if (!res) return null; + + return { + token: this.encodeInviteToken(companyId, workspaceId, userId, res.invite_token), + }; + } + + async createInviteToken( + companyId: string, + workspaceId: string, + userId: string, + context?: ExecutionContext, + ): Promise { + await this.deleteInviteToken(companyId, workspaceId, userId); + const token = randomBytes(32).toString("base64"); + const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId }; + await this.workspaceInviteTokensRepository.save( + getWorkspaceInviteTokensInstance({ ...pk, invite_token: token }), + context, + ); + return { + token: this.encodeInviteToken(companyId, workspaceId, userId, token, context), + }; + } + + async deleteInviteToken( + companyId: string, + workspaceId: string, + userId: string, + context?: ExecutionContext, + ): Promise { + const pk = { company_id: companyId, workspace_id: workspaceId, user_id: userId }; + const currentRecord = await this.workspaceInviteTokensRepository.findOne( + pk, + undefined, + context, + ); + if (!currentRecord) { + return false; + } + await this.workspaceInviteTokensRepository.remove(currentRecord, context); + return true; + } + + async getInviteTokenInfo( + encodedToken: string, + context?: ExecutionContext, + ): Promise { + let tokenInfo: InviteTokenObject; + try { + tokenInfo = this.decodeInviteToken(encodedToken, context); + } catch (e) {} + + if (!tokenInfo) { + return null; + } + + const pk: WorkspaceInviteTokensPrimaryKey = { + company_id: tokenInfo.c, + workspace_id: tokenInfo.w, + user_id: tokenInfo.u, + invite_token: tokenInfo.t, + }; + return this.workspaceInviteTokensRepository.findOne(pk, {}, context); + } + + public encodeInviteToken( + companyId: string, + workspaceId: string, + userId: string, + token: string, + context?: ExecutionContext, + ) { + // Change base64 characters to make them url safe + token = token.replace(/\+/g, ".").replace(/\//g, "_").replace(/=/g, "-"); + const encodedToken = `${reduceUUID4(companyId)}-${reduceUUID4(workspaceId)}-${reduceUUID4( + userId, + )}-${token}`; + return encodedToken; + } + + public decodeInviteToken( + encodedToken: string, + context?: ExecutionContext, + ): InviteTokenObject | null { + try { + const split = encodedToken.split("-"); + //We split on "-" but the token can contain "-" so be careful + // eslint-disable-next-line prefer-const + let [companyId, workspaceId, userId, token] = [ + split.shift(), + split.shift(), + split.shift(), + split.join("-"), + ]; + if (!token) { + return; + } + // Change back url safe characters to base64 + token = token.replace(/\./g, "+").replace(/_/g, "/").replace(/-/g, "="); + return { + c: expandUUID4(companyId), + w: expandUUID4(workspaceId), + u: expandUUID4(userId), + t: token, + }; + } catch (e) { + return null; + } + } + + async ensureUserNotInCompanyIsNotInWorkspace( + userPk: UserPrimaryKey, + companyId: string, + context?: ExecutionContext, + ) { + const workspaces = await this.getAllForCompany(companyId); + for (const workspace of workspaces) { + const companyUser = await gr.services.companies.getCompanyUser( + { id: workspace.company_id }, + userPk, + context, + ); + if (!companyUser) { + logger.warn( + `User ${userPk.id} is not in company ${workspace.company_id} so removing from workspace ${workspace.id}`, + ); + this.removeUser({ workspaceId: workspace.id, userId: userPk.id }, companyId, context).then( + () => null, + ); + } + } + } +} diff --git a/twake/backend/node/src/services/workspaces/services/workspace/index.ts b/twake/backend/node/src/services/workspaces/services/workspace/index.ts deleted file mode 100644 index c7e2002196..0000000000 --- a/twake/backend/node/src/services/workspaces/services/workspace/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { UsersServiceAPI, CompaniesServiceAPI } from "../../../user/api"; -import { WorkspaceService } from "./service"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; -import { ApplicationServiceAPI } from "../../../applications/api"; -import AuthServiceAPI from "../../../../core/platform/services/auth/provider"; - -export function getService( - platformServices: PlatformServicesAPI, - user: UsersServiceAPI, - companies: CompaniesServiceAPI, - applications: ApplicationServiceAPI, - auth: AuthServiceAPI, -): WorkspaceService { - return new WorkspaceService(platformServices, user, companies, applications, auth); -} diff --git a/twake/backend/node/src/services/workspaces/services/workspace/service.ts b/twake/backend/node/src/services/workspaces/services/workspace/service.ts deleted file mode 100644 index 593c86db22..0000000000 --- a/twake/backend/node/src/services/workspaces/services/workspace/service.ts +++ /dev/null @@ -1,617 +0,0 @@ -import { concat, EMPTY, from, Observable } from "rxjs"; -import { mergeMap } from "rxjs/operators"; -import { - CreateResult, - CrudExeption, - DeleteResult, - ExecutionContext, - ListResult, - OperationType, - Paginable, - Pagination, - SaveResult, - UpdateResult, -} from "../../../../core/platform/framework/api/crud-service"; -import Repository from "../../../../core/platform/services/database/services/orm/repository/repository"; -import { WorkspaceServiceAPI } from "../../api"; -import WorkspaceUser, { - getInstance as getWorkspaceUserInstance, - TYPE as WorkspaceUserType, - WorkspaceUserPrimaryKey, -} from "../../../workspaces/entities/workspace_user"; -import Workspace, { - getInstance as getWorkspaceInstance, - TYPE, - TYPE as WorkspaceType, - WorkspacePrimaryKey, -} from "../../../workspaces/entities/workspace"; -import { WorkspaceExecutionContext, WorkspaceUserRole } from "../../types"; -import User, { UserPrimaryKey } from "../../../user/entities/user"; -import { CompanyPrimaryKey } from "../../../user/entities/company"; -import _, { merge } from "lodash"; -import WorkspacePendingUser, { - TYPE as WorkspacePendingUserType, - WorkspacePendingUserPrimaryKey, -} from "../../entities/workspace_pending_users"; -import { CompanyUserRole } from "../../../user/web/types"; -import { uuid } from "../../../../utils/types"; -import { CompaniesServiceAPI, UsersServiceAPI } from "../../../user/api"; -import { CounterProvider } from "../../../../core/platform/services/counter/provider"; -import { - TYPE as WorkspaceCounterEntityType, - WorkspaceCounterEntity, - WorkspaceCounterPrimaryKey, -} from "../../entities/workspace_counters"; -import { PlatformServicesAPI } from "../../../../core/platform/services/platform-services"; -import { countRepositoryItems } from "../../../../utils/counters"; -import { ApplicationServiceAPI } from "../../../applications/api"; -import { RealtimeSaved } from "../../../../core/platform/framework"; -import { ResourcePath } from "../../../../core/platform/services/realtime/types"; -import { getRoomName, getWorkspacePath } from "../../realtime"; -import { InviteTokenObject, WorkspaceInviteTokenObject } from "../../web/types"; -import WorkspaceInviteTokens, { - TYPE as WorkspaceInviteTokensType, - getInstance as getWorkspaceInviteTokensInstance, - WorkspaceInviteTokensPrimaryKey, -} from "../../entities/workspace_invite_tokens"; -import AuthServiceAPI from "../../../../core/platform/services/auth/provider"; -import { randomBytes } from "crypto"; -import { ConsoleOptions, ConsoleType } from "../../../console/types"; -import { Readable } from "stream"; - -export class WorkspaceService implements WorkspaceServiceAPI { - version: "1"; - private workspaceUserRepository: Repository; - private workspaceRepository: Repository; - private workspacePendingUserRepository: Repository; - private workspaceCounter: CounterProvider; - private workspaceInviteTokensRepository: Repository; - - constructor( - private platformServices: PlatformServicesAPI, - private users: UsersServiceAPI, - private companies: CompaniesServiceAPI, - private applications: ApplicationServiceAPI, - private auth: AuthServiceAPI, - ) {} - - async init(): Promise { - this.workspaceUserRepository = - await this.platformServices.database.getRepository( - WorkspaceUserType, - WorkspaceUser, - ); - - this.workspaceRepository = await this.platformServices.database.getRepository( - WorkspaceType, - Workspace, - ); - - const workspaceCountersRepository = - await this.platformServices.database.getRepository( - WorkspaceCounterEntityType, - WorkspaceCounterEntity, - ); - - this.workspacePendingUserRepository = - await this.platformServices.database.getRepository( - WorkspacePendingUserType, - WorkspacePendingUser, - ); - - this.workspaceCounter = await this.platformServices.counter.getCounter( - workspaceCountersRepository, - ); - - this.workspaceCounter.reviseCounter(async (pk: WorkspaceCounterPrimaryKey) => { - if (pk.counter_type == "members") { - return countRepositoryItems(this.workspaceUserRepository, { workspace_id: pk.id }); - } - return 0; - }); - - this.workspaceInviteTokensRepository = - await this.platformServices.database.getRepository( - WorkspaceInviteTokensType, - WorkspaceInviteTokens, - ); - - return this; - } - - get(pk: WorkspacePrimaryKey): Promise { - return this.workspaceRepository.findOne(pk); - } - - async create(workspace: Workspace, context?: ExecutionContext): Promise> { - const workspaceToCreate: Workspace = getWorkspaceInstance({ - ...workspace, - ...{ - name: await this.getWorkspaceName(workspace.name, workspace.company_id, workspace.id), - dateAdded: Date.now(), - isDeleted: false, - isArchived: false, - }, - }); - - const userId = context?.user?.id || ""; - - const created = await this.save( - workspaceToCreate, - {}, - { company_id: workspace.company_id, user: { id: userId, server_request: true } }, - ); - - await this.applications.companyApplications.initWithDefaultApplications( - created.entity.company_id, - { - company: { id: created.entity.company_id }, - user: { id: userId, server_request: true }, - }, - ); - - return new CreateResult(TYPE, created.entity); - } - - update?( - pk: Partial>, - item: Workspace, - context?: ExecutionContext, - ): Promise> { - throw new Error("Method not implemented."); - } - - @RealtimeSaved((workspace, context) => [ - { - // FIXME: For now the room is defined at the company level - // It meay be good to have a special room where just some users are receiving this event - room: ResourcePath.get(getRoomName(workspace)), - path: getWorkspacePath(workspace, context as WorkspaceExecutionContext), - }, - ]) - async save( - item: Partial, - options?: SaveOptions & { logo_b64?: string }, - context?: WorkspaceExecutionContext, - ): Promise> { - let workspace = getWorkspaceInstance({ - ...item, - ...{ - company_id: (context.user.server_request ? item.company_id : null) || context.company_id, - name: "", - dateAdded: Date.now(), - isArchived: false, - isDefault: false, - }, - }); - - if (item.id && !context?.user?.server_request) { - // ON UPDATE - workspace = await this.get({ - id: item.id, - company_id: context.company_id, - }); - - if (!workspace) { - throw new Error(`Unable to edit inexistent workspace ${item.id}`); - } - } - - const logoInternalPath = `/workspaces/${workspace.id}/thumbnail.png`; - const logoPublicPath = `/internal/services/workspaces/v1/companies/${ - workspace.company_id - }/workspaces/${workspace.id}/thumbnail?t=${new Date().getTime()}`; - let logoPublicUrl = undefined; - if (workspace.logo) { - if (!item.logo || options.logo_b64) { - await this.platformServices.storage.remove(logoInternalPath); - workspace.logo = null; - } - } - if (options.logo_b64) { - var s = new Readable(); - s.push(Buffer.from(options.logo_b64.split(",").pop(), "base64")); - s.push(null); - await this.platformServices.storage.write(logoInternalPath, s); - logoPublicUrl = logoPublicPath; - } - - workspace = merge(workspace, { - name: await this.getWorkspaceName(item.name, context.company_id, workspace.id), - logo: logoPublicUrl || workspace.logo, - isArchived: item.isArchived, - isDefault: item.isDefault, - }); - - await this.workspaceRepository.save(workspace); - - if (!item.id && context.user.id) { - await this.addUser( - { id: workspace.id, company_id: workspace.company_id }, - { id: context.user.id }, - "moderator", - ); - } - - if (!item.id) { - this.platformServices.pubsub.publish("workspace:added", { - data: { - company_id: workspace.company_id, - workspace_id: workspace.id, - }, - }); - } - - return new SaveResult( - TYPE, - workspace, - item.id ? OperationType.UPDATE : OperationType.CREATE, - ); - } - - async thumbnail(workspaceId: string) { - const logoInternalPath = `/workspaces/${workspaceId}/thumbnail.png`; - const file = await this.platformServices.storage.read(logoInternalPath); - return { file }; - } - - async delete( - pk: Partial>, - context?: WorkspaceExecutionContext, - ): Promise> { - const primaryKey: Workspace = merge(new Workspace(), { - company_id: context.company_id, - id: pk.id, - }); - await this.workspaceRepository.remove(primaryKey); - return new DeleteResult(TYPE, primaryKey, true); - } - - list( - pagination: Pagination, - options?: ListOptions, - context?: WorkspaceExecutionContext, - ): Promise> { - const pk = { company_id: context.company_id }; - - return this.workspaceRepository.find(pk, { pagination }); - } - - async getAllForCompany(companyId: uuid): Promise { - let allCompanyWorkspaces: Workspace[] = []; - let nextPage: Pagination = new Pagination("", "100"); - do { - const tmp = await this.workspaceRepository.find( - { company_id: companyId }, - { pagination: nextPage }, - ); - nextPage = tmp.nextPage as Pagination; - allCompanyWorkspaces = [...allCompanyWorkspaces, ...tmp.getEntities()]; - } while (nextPage.page_token); - - //Check there is at least one workspace in this company or enforce one - if (allCompanyWorkspaces.length == 0) { - const created = await this.create( - getWorkspaceInstance({ - company_id: companyId, - name: "Home", - isDefault: true, - }), - ); - allCompanyWorkspaces.push(created.entity); - } - - return allCompanyWorkspaces; - } - - async addUser( - workspacePk: WorkspacePrimaryKey, - userPk: UserPrimaryKey, - role: WorkspaceUserRole, - ): Promise { - const wurPk = { - workspaceId: workspacePk.id, - userId: userPk.id, - }; - - const alreadyExists = await this.getUser(wurPk); - if (!alreadyExists) { - await this.userCounterIncrease(workspacePk.id, 1); - } - - await this.workspaceUserRepository.save( - getWorkspaceUserInstance({ - workspaceId: workspacePk.id, - userId: userPk.id, - role: role, - }), - ); - - await this.platformServices.pubsub.publish("workspace:member:added", { - data: { - company_id: workspacePk.company_id, - workspace_id: workspacePk.id, - user_id: userPk.id, - }, - }); - - this; - } - - async updateUserRole( - workspaceUserPk: WorkspaceUserPrimaryKey, - role: WorkspaceUserRole, - ): Promise { - const workspaceUser = await this.getUser(workspaceUserPk); - if (!workspaceUser) { - throw CrudExeption.notFound("WorkspaceUser entity not found"); - } - await this.workspaceUserRepository.save(merge(workspaceUser, { role })); - } - - async checkWorkspaceHasOtherAdmin(workspaceUserPk: WorkspaceUserPrimaryKey): Promise { - //TODO: not implemented, we should check there is still an admin in the workspace before removal. - // Note: company admin and owner are always workspace admins. - return true; - } - - async removeUser( - workspaceUserPk: WorkspaceUserPrimaryKey, - ): Promise> { - const entity = await this.getUser(workspaceUserPk); - - if (!entity) { - throw CrudExeption.notFound("WorkspaceUser entity not found"); - } - - if (!(await this.checkWorkspaceHasOtherAdmin(workspaceUserPk))) { - throw CrudExeption.notFound("No other admin found in workspace"); - } - - await this.workspaceUserRepository.remove(entity); - await this.userCounterIncrease(workspaceUserPk.workspaceId, -1); - return new DeleteResult(WorkspaceUserType, workspaceUserPk, true); - } - - getUsers( - workspaceId: Pick, - pagination?: Paginable, - ): Promise> { - return this.workspaceUserRepository.find( - { workspace_id: workspaceId.workspaceId }, - { pagination: { limitStr: pagination?.limitStr, page_token: pagination?.page_token } }, - ); - } - - getUser( - workspaceUserPk: Pick, - ): Promise { - return this.workspaceUserRepository.findOne({ - workspace_id: workspaceUserPk.workspaceId, - user_id: workspaceUserPk.userId, - }); - } - - async processPendingUser(user: User): Promise { - const userCompanies = await this.companies.getAllForUser(user.id); - for (const userCompany of userCompanies) { - const workspaces = await this.getAllForCompany(userCompany.group_id); - for (const workspace of workspaces) { - const pendingUserPk = { - workspace_id: workspace.id, - email: user.email_canonical, - }; - const pendingUser = await this.getPendingUser(pendingUserPk); - - if (pendingUser) { - await this.removePendingUser(pendingUserPk); - await this.addUser( - { id: workspace.id, company_id: workspace.company_id }, - { id: user.id }, - pendingUser.role, - ); - } - } - } - } - - async getAllForUser( - userId: Pick, - companyId: CompanyPrimaryKey, - ): Promise { - //Process pending invitation to workspace for this user - const user = await this.users.get({ id: userId.userId }); - await this.processPendingUser(user); - - //Get all workspaces for this user - const allCompanyWorkspaces = await this.getAllForCompany(companyId.id); - const userWorkspaces = ( - await Promise.all( - allCompanyWorkspaces.map(workspace => - this.workspaceUserRepository.findOne({ - user_id: userId.userId, - workspace_id: workspace.id, - }), - ), - ) - ).filter(uw => uw); - - //If user is in no workspace, then it must be invited in the default workspaces, expect if he's guest - if (userWorkspaces.length === 0) { - for (const workspace of allCompanyWorkspaces) { - if (workspace.isDefault && !workspace.isArchived && !workspace.isDeleted) { - try { - //Role will match the company role in the default workspaces - const companyRole = await this.companies.getCompanyUser( - { id: companyId.id }, - { id: userId.userId }, - ); - let role: WorkspaceUserRole = "member"; - if (companyRole.role == "admin" || companyRole.role == "owner") role = "moderator"; - - if (companyRole.role !== "guest") { - await this.addUser(workspace, { id: userId.userId }, role); - const uw = await this.workspaceUserRepository.findOne({ - user_id: userId.userId, - workspace_id: workspace.id, - }); - if (uw) { - userWorkspaces.push(uw); - } - } - } catch (err) { - console.log(err); - } - } - } - } - - return userWorkspaces; - } - - getAllUsers$( - workspaceId: Pick, - pagination?: Paginable, - ): Observable { - return from(this.getUsers(workspaceId, pagination)).pipe( - mergeMap(workspaceUsers => { - const items$ = from(workspaceUsers.getEntities()); - const next$ = workspaceUsers?.nextPage?.page_token - ? this.getAllUsers$(workspaceId, workspaceUsers.nextPage) - : EMPTY; - - return concat(items$, next$); - }), - ); - } - - async addPendingUser( - primaryKey: WorkspacePendingUserPrimaryKey, - workspaceRole: WorkspaceUserRole, - companyRole: CompanyUserRole, - ): Promise { - if (await this.getPendingUser(primaryKey)) { - throw CrudExeption.badRequest("User is pending already"); - } - const workspacePendingUser = merge(new WorkspacePendingUser(), { - workspace_id: primaryKey.workspace_id, - email: primaryKey.email, - role: workspaceRole, - company_role: companyRole, - }); - await this.workspacePendingUserRepository.save(workspacePendingUser); - } - - getPendingUser(primaryKey: WorkspacePendingUserPrimaryKey): Promise { - return this.workspacePendingUserRepository.findOne(primaryKey); - } - - async getPendingUsers( - primaryKey: Pick, - ): Promise { - return this.workspacePendingUserRepository.find(primaryKey).then(a => a.getEntities()); - } - - async removePendingUser( - primaryKey: WorkspacePendingUserPrimaryKey, - ): Promise> { - const pendingUser = await this.getPendingUser(primaryKey); - if (!pendingUser) { - throw CrudExeption.notFound("Pending user not found"); - } - await this.workspacePendingUserRepository.remove(pendingUser); - return new DeleteResult(WorkspacePendingUserType, primaryKey, true); - } - - /** - * @name GetWorkspaceName - * @param exceptedName workspace name that user excepted to have - * @param companyId company that user excepted to create or update the workspace - * @returns if workspace name is already used in the company, this will return the exceptedName with the current duplicates number otherwise simply return the exceptedName - */ - private async getWorkspaceName(exceptedName: string, companyId: string, workspaceId: string) { - const workspacesList = await this.list( - null, - {}, - { company_id: companyId, user: { id: null, server_request: true } }, - ); - - workspacesList.filterEntities( - entity => entity.id !== workspaceId && _.includes(entity.name, exceptedName), - ); - - const shouldRenameWorkspace = !workspacesList.isEmpty(); - const duplicatesCount = workspacesList.getEntities().length; - - return shouldRenameWorkspace ? `${exceptedName}(${duplicatesCount + 1})` : exceptedName; - } - - private wsCountPk = (id: string) => ({ id, counter_type: "members" }); - - private userCounterIncrease(workspaceId: string, increaseValue: number) { - return this.workspaceCounter.increase(this.wsCountPk(workspaceId), increaseValue); - } - - getUsersCount(workspaceId: string): Promise { - return this.workspaceCounter.get(this.wsCountPk(workspaceId)); - } - - private jwtInviteToken(companyId: string, workspaceId: string, token: string) { - const inviteTokenObject: InviteTokenObject = { c: companyId, w: workspaceId, t: token }; - return this.auth.sign(inviteTokenObject); - } - - async getInviteToken( - companyId: string, - workspaceId: string, - ): Promise { - const pk = { company_id: companyId, workspace_id: workspaceId }; - const res = await this.workspaceInviteTokensRepository.findOne(pk); - if (!res) return null; - - return { - token: this.jwtInviteToken(companyId, workspaceId, res.invite_token), - }; - } - - async createInviteToken( - companyId: string, - workspaceId: string, - ): Promise { - await this.deleteInviteToken(companyId, workspaceId); - const token = randomBytes(32).toString("base64"); - const pk = { company_id: companyId, workspace_id: workspaceId }; - await this.workspaceInviteTokensRepository.save( - getWorkspaceInviteTokensInstance({ ...pk, invite_token: token }), - ); - return { - token: this.jwtInviteToken(companyId, workspaceId, token), - }; - } - async deleteInviteToken(companyId: string, workspaceId: string): Promise { - const pk = { company_id: companyId, workspace_id: workspaceId }; - const currentRecord = await this.workspaceInviteTokensRepository.findOne(pk); - if (currentRecord) { - await this.workspaceInviteTokensRepository.remove(currentRecord); - } - return !!currentRecord; - } - - async getInviteTokenInfo(jwtToken: string): Promise { - let tokenInfo: InviteTokenObject; - try { - tokenInfo = await this.auth.verifyTokenObject(jwtToken); - } catch (e) {} - - if (!tokenInfo) { - return null; - } - - const pk: WorkspaceInviteTokensPrimaryKey = { - company_id: tokenInfo.c, - workspace_id: tokenInfo.w, - invite_token: tokenInfo.t, - }; - return this.workspaceInviteTokensRepository.findOne(pk); - } -} diff --git a/twake/backend/node/src/services/workspaces/web/controllers/workspace-invite-tokens.ts b/twake/backend/node/src/services/workspaces/web/controllers/workspace-invite-tokens.ts index 81cc186944..ef4653f79e 100644 --- a/twake/backend/node/src/services/workspaces/web/controllers/workspace-invite-tokens.ts +++ b/twake/backend/node/src/services/workspaces/web/controllers/workspace-invite-tokens.ts @@ -5,7 +5,6 @@ import { ResourceGetResponse, ResourceListResponse, } from "../../../../utils/types"; -import WorkspaceServicesAPI from "../../api"; import { WorkspaceInviteTokenDeleteRequest, WorkspaceInviteTokenGetRequest, @@ -16,8 +15,11 @@ import { import { FastifyReply, FastifyRequest } from "fastify"; import { WorkspaceInviteTokensExecutionContext } from "../../types"; -import { CrudExeption } from "../../../../core/platform/framework/api/crud-service"; +import { CrudException } from "../../../../core/platform/framework/api/crud-service"; import { pick } from "lodash"; +import { ConsoleCompany } from "../../../console/types"; +import { formatCompany, getCompanyStats } from "../../../../services/user/utils"; +import gr from "../../../global-resolver"; export class WorkspaceInviteTokensCrudController implements @@ -28,23 +30,20 @@ export class WorkspaceInviteTokensCrudController ResourceDeleteResponse > { - constructor(protected services: WorkspaceServicesAPI) { - this.services = services; - } - async list( request: FastifyRequest<{ Params: WorkspaceInviteTokenGetRequest }>, reply: FastifyReply, ): Promise> { const context = getExecutionContext(request); - const res = await this.services.workspaces.getInviteToken( + const res = await gr.services.workspaces.getInviteToken( context.company_id, context.workspace_id, + context.user.id, ); if (!res) { - throw CrudExeption.notFound("Invite token not found"); + throw CrudException.notFound("Invite token not found"); } return { @@ -58,9 +57,10 @@ export class WorkspaceInviteTokensCrudController ): Promise> { const context = getExecutionContext(request); - const res = await this.services.workspaces.createInviteToken( + const res = await gr.services.workspaces.createInviteToken( context.company_id, context.workspace_id, + context.user.id, ); return { @@ -74,13 +74,20 @@ export class WorkspaceInviteTokensCrudController ): Promise { const context = getExecutionContext(request); - const deleted = await this.services.workspaces.deleteInviteToken( + const tokenInfo = gr.services.workspaces.decodeInviteToken(request.params.token); + + if (!tokenInfo) { + throw CrudException.notFound("Invite token malformed"); + } + + const deleted = await gr.services.workspaces.deleteInviteToken( context.company_id, context.workspace_id, + context.user.id, ); if (!deleted) { - throw CrudExeption.notFound("Invite token not found"); + throw CrudException.notFound("Invite token not found"); } reply.code(204); @@ -94,29 +101,29 @@ export class WorkspaceInviteTokensCrudController request: FastifyRequest<{ Body: WorkspaceJoinByTokenRequest }>, reply: FastifyReply, ): Promise> { - const consoleUrl = this.services.console.consoleOptions.url; - // if (!consoleUrl) { - // throw CrudExeption.badRequest("Console url is not defined"); - // } - - const entity = await this.services.workspaces.getInviteTokenInfo(request.body.token); + const entity = await gr.services.workspaces.getInviteTokenInfo(request.body.token); if (!entity) { - throw CrudExeption.notFound("Token not found"); + throw CrudException.notFound("Token not found"); } const { company_id, workspace_id } = entity; const [company, workspace] = await Promise.all([ - this.services.companies.getCompany({ id: company_id }), - this.services.workspaces.get({ + gr.services.companies.getCompany({ id: company_id }), + gr.services.workspaces.get({ company_id: company_id, id: workspace_id, }), ]); + const total_messages = await gr.services.statistics.get(company.id, "messages"); const resource: WorkspaceJoinByTokenResponse = { - company: { name: company.name }, + company: { + name: company.name, + stats: formatCompany(company, undefined, getCompanyStats(company, total_messages))?.stats, + plan: formatCompany(company, undefined, getCompanyStats(company, total_messages))?.plan, + }, workspace: { name: workspace.name }, auth_required: false, }; @@ -125,24 +132,59 @@ export class WorkspaceInviteTokensCrudController resource.auth_required = true; } else { if (request.body.join) { - const user_id = request.currentUser.id; + const userId = request.currentUser.id; + const user = await gr.services.users.get({ id: userId }); - const companyUser = await this.services.companies.getCompanyUser( + let companyUser = await gr.services.companies.getCompanyUser( { id: company_id }, - { id: user_id }, + { id: userId }, ); if (!companyUser) { - await this.services.companies.setUserRole(company_id, user_id, "member"); + const inviter = await gr.services.users.get({ + id: entity.user_id, + }); + + await gr.services.console + .getClient() + .addUserToCompany( + { id: company.id, code: company.identity_provider_id } as ConsoleCompany, + { + id: userId, + email: request.currentUser.email, + password: null, + firstName: null, + lastName: null, + name: null, + avatar: { + type: null, + value: null, + }, + role: "member", + skipInvite: false, + inviterEmail: inviter.email_canonical, + }, + ); + + await gr.services.console + .getClient() + .updateLocalUserFromConsole(user.identity_provider_id); + companyUser = await gr.services.companies.getCompanyUser( + { id: company_id }, + { id: userId }, + ); + } + if (!companyUser) { + throw CrudException.badRequest("Unable to add user to the company"); } - const workspaceUser = await this.services.workspaces.getUser({ + const workspaceUser = await gr.services.workspaces.getUser({ workspaceId: workspace.id, - userId: user_id, + userId: userId, }); if (!workspaceUser) { - await this.services.workspaces.addUser( + await gr.services.workspaces.addUser( pick(workspace, ["company_id", "id"]), - { id: user_id }, + { id: userId }, "member", ); } diff --git a/twake/backend/node/src/services/workspaces/web/controllers/workspace-users.ts b/twake/backend/node/src/services/workspaces/web/controllers/workspace-users.ts index 92325e2cb7..3d5a7f84dc 100644 --- a/twake/backend/node/src/services/workspaces/web/controllers/workspace-users.ts +++ b/twake/backend/node/src/services/workspaces/web/controllers/workspace-users.ts @@ -6,7 +6,6 @@ import { ResourceListResponse, uuid, } from "../../../../utils/types"; -import { WorkspaceServiceAPI } from "../../api"; import { WorkspacePendingUserRequest, WorkspaceUserInvitationResponse, @@ -19,7 +18,6 @@ import { WorkspaceUsersRequest, } from "../types"; import { FastifyReply, FastifyRequest } from "fastify"; -import { CompaniesServiceAPI, UsersServiceAPI } from "../../../user/api"; import { WorkspaceUsersExecutionContext } from "../../types"; import WorkspaceUser from "../../entities/workspace_user"; @@ -29,13 +27,14 @@ import { CompanyShort, CompanyUserRole, CompanyUserStatus } from "../../../user/ import Company from "../../../user/entities/company"; import { chain } from "lodash"; import { - CrudExeption, + CrudException, ListResult, Pagination, } from "../../../../core/platform/framework/api/crud-service"; import WorkspacePendingUser from "../../entities/workspace_pending_users"; -import { ConsoleServiceAPI } from "../../../console/api"; import { ConsoleCompany, CreateConsoleUser } from "../../../console/types"; +import { hasCompanyAdminLevel } from "../../../../utils/company"; +import gr from "../../../global-resolver"; export class WorkspaceUsersCrudController implements @@ -46,13 +45,6 @@ export class WorkspaceUsersCrudController ResourceDeleteResponse > { - constructor( - protected workspaceService: WorkspaceServiceAPI, - protected companyService: CompaniesServiceAPI, - protected usersService: UsersServiceAPI, - protected consoleService: ConsoleServiceAPI, - ) {} - private formatWorkspaceUser( workspaceUser: WorkspaceUser, currentCompanyId: uuid, @@ -60,6 +52,15 @@ export class WorkspaceUsersCrudController userCompanies: CompanyUser[], companiesMap: Map, ): WorkspaceUserObject { + //Company admins should be workspace moderators automatically + if ( + currentCompanyId && + userCompanies && + hasCompanyAdminLevel(userCompanies.find(uc => uc.group_id === currentCompanyId)?.role) + ) { + workspaceUser.role = "moderator"; + } + const res: WorkspaceUserObject = { id: workspaceUser.id, company_id: currentCompanyId, @@ -82,6 +83,9 @@ export class WorkspaceUsersCrudController deleted: Boolean(user.deleted), status: user.status_icon, last_activity: user.last_activity, + cache: { + companies: user.cache?.companies || [], + }, companies: userCompanies .filter(cu => companiesMap.get(cu.group_id)) .map(cu => { @@ -110,7 +114,7 @@ export class WorkspaceUsersCrudController .map("group_id") .uniq() .value() - .map(companyId => this.companyService.getCompany({ id: companyId })), + .map(companyId => gr.services.companies.getCompany({ id: companyId })), ) ) .filter(c => c) @@ -131,7 +135,7 @@ export class WorkspaceUsersCrudController let allWorkspaceUsers: WorkspaceUser[] = []; if (request.query.search) { - const users: ListResult = await this.usersService.search( + const users: ListResult = await gr.services.users.search( new Pagination(request.query.page_token, request.query.limit), { search: request.query.search, @@ -143,7 +147,7 @@ export class WorkspaceUsersCrudController nextPageToken = users.nextPage?.page_token; for (const user of users.getEntities()) { - const res = await this.workspaceService.getUser({ + const res = await gr.services.workspaces.getUser({ workspaceId: context.workspace_id, userId: user.id, }); @@ -151,7 +155,7 @@ export class WorkspaceUsersCrudController if (res) allWorkspaceUsers.push(res); } } else { - const result = await this.workspaceService.getUsers( + const result = await gr.services.workspaces.getUsers( { workspaceId: context.workspace_id, }, @@ -166,14 +170,14 @@ export class WorkspaceUsersCrudController const allUsersMap = new Map( ( await Promise.all( - allWorkspaceUsers.map(wu => this.usersService.get({ id: wu.userId })), + allWorkspaceUsers.map(wu => gr.services.users.get({ id: wu.userId })), ).then(users => users.filter(a => a)) ).map(user => [user.id, user]), ); const allCompanyUsers: CompanyUser[] = [].concat( ...(await Promise.all( - allWorkspaceUsers.map(wu => this.usersService.getUserCompanies({ id: wu.userId })), + allWorkspaceUsers.map(wu => gr.services.users.getUserCompanies({ id: wu.userId })), )), ); @@ -210,18 +214,18 @@ export class WorkspaceUsersCrudController userId: uuid, context: WorkspaceUsersExecutionContext, ): Promise { - const workspaceUser = await this.workspaceService.getUser({ + const workspaceUser = await gr.services.workspaces.getUser({ workspaceId: context.workspace_id, userId: userId, }); - const user = await this.usersService.get({ id: userId }); + const user = await gr.services.users.get({ id: userId }); if (!user) { - throw CrudExeption.badRequest("User entity not found"); + throw CrudException.badRequest("User entity not found"); } - const userCompanies: CompanyUser[] = await this.usersService.getUserCompanies({ id: userId }); + const userCompanies: CompanyUser[] = await gr.services.users.getUserCompanies({ id: userId }); const companiesMap = await this.getCompaniesMap(userCompanies); @@ -255,16 +259,16 @@ export class WorkspaceUsersCrudController const userId = request.params.user_id || request.body.resource.user_id; const role = request.body.resource.role; - const companyUser = await this.companyService.getCompanyUser( + const companyUser = await gr.services.companies.getCompanyUser( { id: context.company_id }, { id: userId }, ); if (!companyUser) { - throw CrudExeption.badRequest(`User ${userId} does not belong to this company`); + throw CrudException.badRequest(`User ${userId} does not belong to this company`); } - const workspaceUser = await this.workspaceService.getUser({ + const workspaceUser = await gr.services.workspaces.getUser({ workspaceId: context.workspace_id, userId: userId, }); @@ -272,16 +276,16 @@ export class WorkspaceUsersCrudController if (request.params.user_id) { // ON UPDATE if (!workspaceUser) { - throw CrudExeption.notFound(`User ${userId} not found in this workspace`); + throw CrudException.notFound(`User ${userId} not found in this workspace`); } - await this.workspaceService.updateUserRole( + await gr.services.workspaces.updateUserRole( { workspaceId: context.workspace_id, userId }, role, ); } else { // ON ADD if (!workspaceUser) { - await this.workspaceService.addUser( + await gr.services.workspaces.addUser( { id: context.workspace_id, company_id: context.company_id }, { id: userId }, role, @@ -297,25 +301,29 @@ export class WorkspaceUsersCrudController resource: resource, }; } + async delete( request: FastifyRequest<{ Params: WorkspaceUsersRequest }>, reply: FastifyReply, ): Promise { const context = getExecutionContext(request); - const workspaceUser = await this.workspaceService.getUser({ + const workspaceUser = await gr.services.workspaces.getUser({ workspaceId: context.workspace_id, userId: request.params.user_id, }); if (!workspaceUser) { - throw CrudExeption.notFound("Default channel has not been found"); + throw CrudException.notFound("Default channel has not been found"); } - await this.workspaceService.removeUser({ - workspaceId: context.workspace_id, - userId: request.params.user_id, - }); + await gr.services.workspaces.removeUser( + { + workspaceId: context.workspace_id, + userId: request.params.user_id, + }, + request.params.company_id, + ); reply.status(204); return { @@ -333,13 +341,13 @@ export class WorkspaceUsersCrudController const context = getExecutionContext(request); const usersInTwake: Map = new Map( - await this.usersService + await gr.services.users .getByEmails(request.body.invitations.map(a => a.email)) .then(users => users.map(user => [user.email_canonical, user])), ); const workspacePendingUsers: Map = new Map( - await this.workspaceService + await gr.services.workspaces .getPendingUsers({ workspace_id: context.workspace_id, }) @@ -349,7 +357,7 @@ export class WorkspaceUsersCrudController const responses: WorkspaceUserInvitationResponseItem[] = []; const putUserToPending = async (invitation: WorkspaceUsersInvitationItem) => { - await this.workspaceService.addPendingUser( + await gr.services.workspaces.addPendingUser( { workspace_id: context.workspace_id, email: invitation.email, @@ -375,7 +383,7 @@ export class WorkspaceUsersCrudController let userInCompany = false; let user: User = null; - const consoleClient = this.consoleService.getClient(); + const consoleClient = gr.services.console.getClient(); if (usersInTwake.has(invitation.email)) { user = usersInTwake.get(invitation.email); @@ -383,7 +391,7 @@ export class WorkspaceUsersCrudController if (user) { userInCompany = Boolean( - await this.companyService.getCompanyUser({ id: context.company_id }, { id: user.id }), + await gr.services.companies.getCompanyUser({ id: context.company_id }, { id: user.id }), ); } } else { @@ -394,7 +402,9 @@ export class WorkspaceUsersCrudController } if (!userInCompany) { - const company = await this.companyService.getCompany({ id: context.company_id }); + const company = await gr.services.companies.getCompany({ + id: context.company_id, + }); const createUser: CreateConsoleUser = { id: user ? user.id : null, email: invitation.email, @@ -417,11 +427,10 @@ export class WorkspaceUsersCrudController createUser, ); } catch (err) { - console.error(err); responses.push({ email: invitation.email, status: "error", - message: "Unable to invite this user to your company" + err, + message: "Unable to invite this user to your company " + err, }); continue; } @@ -429,7 +438,7 @@ export class WorkspaceUsersCrudController const userInWorkspace = Boolean( user && - (await this.workspaceService.getUser({ + (await gr.services.workspaces.getUser({ workspaceId: context.workspace_id, userId: user.id, })), @@ -447,7 +456,7 @@ export class WorkspaceUsersCrudController } await Promise.all( - usersToProcessImmediately.map(user => this.consoleService.processPendingUser(user)), + usersToProcessImmediately.map(user => gr.services.console.processPendingUser(user)), ); return { @@ -460,7 +469,7 @@ export class WorkspaceUsersCrudController reply: FastifyReply, ): Promise { try { - await this.workspaceService.removePendingUser({ + await gr.services.workspaces.removePendingUser({ workspace_id: request.params.workspace_id, email: request.params.email, }); @@ -478,7 +487,7 @@ export class WorkspaceUsersCrudController request: FastifyRequest<{ Params: WorkspacePendingUserRequest }>, reply: FastifyReply, ): Promise> { - const resources = await this.workspaceService.getPendingUsers({ + const resources = await gr.services.workspaces.getPendingUsers({ workspace_id: request.params.workspace_id, }); diff --git a/twake/backend/node/src/services/workspaces/web/controllers/workspaces.ts b/twake/backend/node/src/services/workspaces/web/controllers/workspaces.ts index 94fa6aef60..7b049f28d5 100644 --- a/twake/backend/node/src/services/workspaces/web/controllers/workspaces.ts +++ b/twake/backend/node/src/services/workspaces/web/controllers/workspaces.ts @@ -5,7 +5,6 @@ import { ResourceGetResponse, ResourceListResponse, } from "../../../../utils/types"; -import { WorkspaceServiceAPI } from "../../api"; import { UpdateWorkspaceBody, WorkspaceBaseRequest, @@ -15,14 +14,18 @@ import { } from "../types"; import { FastifyReply, FastifyRequest } from "fastify"; import Workspace from "../../entities/workspace"; -import { CompaniesServiceAPI } from "../../../user/api"; -import { WorkspaceExecutionContext, WorkspaceUserRole } from "../../types"; +import { WorkspaceExecutionContext } from "../../types"; import { plainToClass } from "class-transformer"; import { hasCompanyAdminLevel, hasCompanyMemberLevel } from "../../../../utils/company"; import { hasWorkspaceAdminLevel } from "../../../../utils/workspace"; import { getWorkspaceRooms } from "../../realtime"; -import { RealtimeServiceAPI } from "../../../../core/platform/services/realtime/api"; -import { CrudExeption } from "../../../../core/platform/framework/api/crud-service"; +import { + CrudException, + ExecutionContext, +} from "../../../../core/platform/framework/api/crud-service"; +import CompanyUser from "../../../user/entities/company_user"; +import gr from "../../../global-resolver"; +import { getLogger, TwakeLogger } from "../../../../core/platform/framework"; export class WorkspacesCrudController implements @@ -33,33 +36,28 @@ export class WorkspacesCrudController ResourceDeleteResponse > { - constructor( - protected realtime: RealtimeServiceAPI, - protected workspaceService: WorkspaceServiceAPI, - protected companyService: CompaniesServiceAPI, - ) {} - - private getCompanyUserRole(context: WorkspaceExecutionContext) { - return this.companyService - .getCompanyUser({ id: context.company_id }, { id: context.user.id }) + private logger: TwakeLogger; + private getCompanyUserRole(companyId: string, userId: string, context?: ExecutionContext) { + return gr.services.companies + .getCompanyUser({ id: companyId }, { id: userId }, context) .then(a => (a ? a.role : null)); } - private getWorkspaceUserRole(workspaceId: string, context: WorkspaceExecutionContext) { - return this.workspaceService - .getUser({ workspaceId, userId: context.user.id }) - .then(a => (a ? a.role : null)); + private getWorkspaceUserRole(workspaceId: string, userId: string, context?: ExecutionContext) { + return gr.services.workspaces + .getUser({ workspaceId, userId }, context) + .then(a => (a ? a.role || "member" : null)); } - private getWorkspaceUsersCount(workspaceId: string) { - return this.workspaceService.getUsersCount(workspaceId); + private getWorkspaceUsersCount(workspaceId: string, context?: ExecutionContext) { + return gr.services.workspaces.getUsersCount(workspaceId, context); } - private static formatWorkspace( + private async formatWorkspace( workspace: Workspace, usersCount: number, - role?: WorkspaceUserRole, - ): WorkspaceObject { + userId?: string, + ): Promise { const res: WorkspaceObject = { id: workspace.id, company_id: workspace.company_id, @@ -74,7 +72,19 @@ export class WorkspacesCrudController total_members: usersCount, }, }; - if (role) { + + if (userId) { + let role = await this.getWorkspaceUserRole(workspace.id, userId); + if (role !== "moderator") { + //Company admins should be workspace moderators automatically + const companyUser: CompanyUser = await gr.services.companies.getCompanyUser( + { id: workspace.company_id }, + { id: userId }, + ); + if (companyUser && hasCompanyAdminLevel(companyUser?.role)) { + role = "moderator"; + } + } res.role = role; } @@ -85,7 +95,7 @@ export class WorkspacesCrudController request: FastifyRequest<{ Params: WorkspaceRequest }>, response: FastifyReply, ): Promise { - const data = await this.workspaceService.thumbnail(request.params.id); + const data = await gr.services.workspaces.thumbnail(request.params.id); const filename = "thumbnail.png"; response.header("Content-disposition", `inline; filename="${filename}"`); @@ -100,27 +110,26 @@ export class WorkspacesCrudController ): Promise> { const context = getExecutionContext(request); - const workspace = await this.workspaceService.get({ + const workspace = await gr.services.workspaces.get({ company_id: context.company_id, id: request.params.id, }); if (!workspace) { - throw CrudExeption.notFound(`Workspace ${request.params.id} not found`); + throw CrudException.notFound(`Workspace ${request.params.id} not found`); } - const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context); - + const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context.user.id); if (!workspaceUserRole) { - const companyUserRole = await this.getCompanyUserRole(context); - + const companyUserRole = await this.getCompanyUserRole(context.company_id, context.user.id); if (companyUserRole !== "admin") { - throw CrudExeption.forbidden(`You are not belong to workspace ${request.params.id}`); + throw CrudException.forbidden(`You are not belong to workspace ${request.params.id}`); } } + const count = await this.getWorkspaceUsersCount(workspace.id); return { - resource: WorkspacesCrudController.formatWorkspace(workspace, count, workspaceUserRole), + resource: await this.formatWorkspace(workspace, count, context.user.id), }; } @@ -129,15 +138,18 @@ export class WorkspacesCrudController ): Promise> { const context = getExecutionContext(request); - const allCompanyWorkspaces = await this.workspaceService.getAllForCompany(context.company_id); + const allCompanyWorkspaces = await gr.services.workspaces.getAllForCompany(context.company_id); - const allUserWorkspaceRolesMap = await this.workspaceService + const allUserWorkspaceRolesMap = await gr.services.workspaces .getAllForUser({ userId: context.user.id }, { id: context.company_id }) .then( uws => // eslint-disable-next-line @typescript-eslint/no-explicit-any new Map( - uws.map(uw => [uw.workspaceId, hasCompanyAdminLevel(uw.role) ? "moderator" : uw.role]), + uws.map(uw => [ + uw.workspaceId, + hasCompanyAdminLevel(uw.role) ? "moderator" : uw.role || "member", + ]), ), ); @@ -148,14 +160,10 @@ export class WorkspacesCrudController return { resources: await Promise.all( userWorkspaces.map(async ws => - WorkspacesCrudController.formatWorkspace( - ws, - await this.getWorkspaceUsersCount(ws.id), - allUserWorkspaceRolesMap.get(ws.id), - ), + this.formatWorkspace(ws, await this.getWorkspaceUsersCount(ws.id), context.user.id), ), ), - websockets: this.realtime.sign(getWorkspaceRooms(context), context.user.id), + websockets: gr.platformServices.realtime.sign(getWorkspaceRooms(context), context.user.id), }; } @@ -164,27 +172,37 @@ export class WorkspacesCrudController reply: FastifyReply, ): Promise> { const context = getExecutionContext(request); - const companyUserRole = await this.getCompanyUserRole(context); + const companyUserRole = await this.getCompanyUserRole(context.company_id, context.user.id); if (!hasCompanyMemberLevel(companyUserRole)) { - throw CrudExeption.forbidden(`You are not a member of company ${context.company_id}`); + throw CrudException.forbidden(`You are not a member of company ${context.company_id}`); } if (!hasCompanyAdminLevel(companyUserRole) && request.params.id) { - const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context); + const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context.user.id); + const companyUserRole = await this.getCompanyUserRole(context.company_id, context.user.id); - if (!hasWorkspaceAdminLevel(workspaceUserRole)) { - throw CrudExeption.forbidden("You are not a admin of workspace or company"); + if (!hasWorkspaceAdminLevel(workspaceUserRole, companyUserRole)) { + throw CrudException.forbidden("You are not a admin of workspace or company"); } } const r = request.body.resource; + const opt = request.body.options; + + const existedEntity = request.params.id + ? await gr.services.workspaces.get({ + company_id: request.params.company_id, + id: request.params.id, + }) + : null; + const entity = plainToClass(Workspace, { ...{ - name: r.name, - logo: r.logo, - isDefault: r.default, - isArchived: r.archived, + name: r.name || existedEntity?.name, + logo: r.logo || existedEntity?.logo, + isDefault: r.default || existedEntity?.isDefault, + isArchived: r.archived || existedEntity?.isArchived, }, ...{ group_id: request.params.company_id, @@ -192,19 +210,17 @@ export class WorkspacesCrudController }, }); - const workspaceEntity = await this.workspaceService - .save(entity, request.body.options || {}, context) + const workspaceEntity = await gr.services.workspaces + .save(entity, opt || {}, context) .then(a => a.entity); request.params.id ? reply.code(200) : reply.code(201); - const workspaceUserRole = await this.getWorkspaceUserRole(workspaceEntity.id, context); - return { - resource: WorkspacesCrudController.formatWorkspace( + resource: await this.formatWorkspace( workspaceEntity, await this.getWorkspaceUsersCount(workspaceEntity.id), - workspaceUserRole, + context.user.id, ), }; } @@ -215,19 +231,20 @@ export class WorkspacesCrudController ): Promise { const context = getExecutionContext(request); - const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context); + const workspaceUserRole = await this.getWorkspaceUserRole(request.params.id, context.user.id); + const companyUserRole = await this.getCompanyUserRole(context.company_id, context.user.id); - if (!hasWorkspaceAdminLevel(workspaceUserRole)) { - const companyUserRole = await this.getCompanyUserRole(context); + if (!hasWorkspaceAdminLevel(workspaceUserRole, companyUserRole)) { + const companyUserRole = await this.getCompanyUserRole(context.company_id, context.user.id); if (companyUserRole !== "admin") { - throw CrudExeption.forbidden("You are not a admin of workspace or company"); + throw CrudException.forbidden("You are not a admin of workspace or company"); } } - const deleteResult = await this.workspaceService.delete( - { id: request.params.id, company_id: context.company_id }, - context, - ); + const deleteResult = await gr.services.workspaces.delete({ + id: request.params.id, + company_id: context.company_id, + }); if (deleteResult.deleted) { reply.code(204); @@ -241,6 +258,10 @@ export class WorkspacesCrudController status: "error", }; } + + constructor() { + this.logger = getLogger("Workspaces controller"); + } } function getExecutionContext( diff --git a/twake/backend/node/src/services/workspaces/web/index.ts b/twake/backend/node/src/services/workspaces/web/index.ts index 8ad4b76831..2f9ff10911 100644 --- a/twake/backend/node/src/services/workspaces/web/index.ts +++ b/twake/backend/node/src/services/workspaces/web/index.ts @@ -1,14 +1,10 @@ import { FastifyInstance, FastifyRegisterOptions } from "fastify"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; -import UserServiceAPI from "../api"; import routes from "./routes"; export default ( fastify: FastifyInstance, options: FastifyRegisterOptions<{ prefix: string; - service: UserServiceAPI; - realtime: RealtimeServiceAPI; }>, ): void => { fastify.log.debug("Configuring /workspaces routes"); diff --git a/twake/backend/node/src/services/workspaces/web/routes.ts b/twake/backend/node/src/services/workspaces/web/routes.ts index af65419545..116d7d0303 100644 --- a/twake/backend/node/src/services/workspaces/web/routes.ts +++ b/twake/backend/node/src/services/workspaces/web/routes.ts @@ -18,38 +18,23 @@ import { updateWorkspaceSchema, updateWorkspaceUserSchema, } from "./schemas"; - -import WorkspaceServicesAPI from "../api"; import { WorkspaceBaseRequest, WorkspaceUsersBaseRequest, WorkspaceUsersRequest } from "./types"; import { WorkspaceUsersCrudController } from "./controllers/workspace-users"; import { hasWorkspaceAdminLevel, hasWorkspaceMemberLevel } from "../../../utils/workspace"; import { WorkspaceInviteTokensCrudController } from "./controllers/workspace-invite-tokens"; import WorkspaceUser from "../entities/workspace_user"; -import { RealtimeServiceAPI } from "../../../core/platform/services/realtime/api"; +import { checkUserBelongsToCompany, hasCompanyMemberLevel } from "../../../utils/company"; +import gr from "../../global-resolver"; const workspacesUrl = "/companies/:company_id/workspaces"; const workspacePendingUsersUrl = "/companies/:company_id/workspaces/:workspace_id/pending"; const workspaceUsersUrl = "/companies/:company_id/workspaces/:workspace_id/users"; const workspaceInviteTokensUrl = "/companies/:company_id/workspaces/:workspace_id/users/tokens"; -const routes: FastifyPluginCallback<{ - service: WorkspaceServicesAPI; - realtime: RealtimeServiceAPI; -}> = (fastify: FastifyInstance, options, next) => { - const workspacesController = new WorkspacesCrudController( - options.realtime, - options.service.workspaces, - options.service.companies, - ); - - const workspaceUsersController = new WorkspaceUsersCrudController( - options.service.workspaces, - options.service.companies, - options.service.users, - options.service.console, - ); - - const workspaceInviteTokensController = new WorkspaceInviteTokensCrudController(options.service); +const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + const workspacesController = new WorkspacesCrudController(); + const workspaceUsersController = new WorkspaceUsersCrudController(); + const workspaceInviteTokensController = new WorkspaceInviteTokensCrudController(); const accessControl = async () => { // TODO @@ -61,25 +46,11 @@ const routes: FastifyPluginCallback<{ }; const companyCheck = async (request: FastifyRequest<{ Params: WorkspaceBaseRequest }>) => { - const companyId = request.params.company_id; - const userId = request.currentUser.id; - - const companyUser = await options.service.companies.getCompanyUser( - { id: companyId }, - { id: userId }, - ); - - if (!companyUser) { - const company = await options.service.companies.getCompany({ id: companyId }); - if (!company) { - throw fastify.httpErrors.notFound(`Company ${companyId} not found`); - } - throw fastify.httpErrors.forbidden("User does not belong to this company"); - } + await checkUserBelongsToCompany(request.currentUser.id, request.params.company_id); }; const checkWorkspace = async (request: FastifyRequest<{ Params: WorkspaceUsersBaseRequest }>) => { - const workspace = await options.service.workspaces.get({ + const workspace = await gr.services.workspaces.get({ company_id: request.params.company_id, id: request.params.workspace_id, }); @@ -94,10 +65,13 @@ const routes: FastifyPluginCallback<{ const companyId = request.params.workspace_id; const workspaceId = request.params.workspace_id; const userId = request.currentUser.id; - const workspaceUser = await options.service.workspaces.getUser({ workspaceId, userId }); + const workspaceUser = await gr.services.workspaces.getUser({ + workspaceId, + userId, + }); if (!workspaceUser) { - const workspace = await options.service.workspaces.get({ + const workspace = await gr.services.workspaces.get({ company_id: companyId, id: workspaceId, }); @@ -110,11 +84,34 @@ const routes: FastifyPluginCallback<{ return workspaceUser; }; + const checkUserHasCompanyMemberLevel = async ( + request: FastifyRequest<{ Params: WorkspaceUsersRequest }>, + ) => { + if (!request.currentUser.id) { + throw fastify.httpErrors.forbidden("You must be authenticated"); + } + const companyUser = await gr.services.companies.getCompanyUser( + { id: request.params.company_id }, + { id: request.currentUser.id }, + ); + + if (!hasCompanyMemberLevel(companyUser?.role)) { + throw fastify.httpErrors.forbidden("Only company member can perform this action"); + } + }; + const checkUserIsWorkspaceAdmin = async ( request: FastifyRequest<{ Params: WorkspaceUsersRequest }>, ) => { + if (!request.currentUser.id) { + throw fastify.httpErrors.forbidden("You must be authenticated"); + } const workspaceUser = await checkUserWorkspace(request); - if (!hasWorkspaceAdminLevel(workspaceUser.role)) { + const companyUser = await gr.services.companies.getCompanyUser( + { id: request.params.company_id }, + { id: request.currentUser.id }, + ); + if (!hasWorkspaceAdminLevel(workspaceUser?.role, companyUser?.role)) { throw fastify.httpErrors.forbidden("Only workspace moderator can perform this action"); } }; @@ -122,8 +119,15 @@ const routes: FastifyPluginCallback<{ const checkUserIsWorkspaceMember = async ( request: FastifyRequest<{ Params: WorkspaceUsersRequest }>, ) => { + if (!request.currentUser.id) { + throw fastify.httpErrors.forbidden("You must be authenticated"); + } const workspaceUser = await checkUserWorkspace(request); - if (!hasWorkspaceMemberLevel(workspaceUser.role)) { + const companyUser = await gr.services.companies.getCompanyUser( + { id: request.params.company_id }, + { id: request.currentUser.id }, + ); + if (!hasWorkspaceMemberLevel(workspaceUser?.role, companyUser?.role)) { throw fastify.httpErrors.forbidden("Only workspace members can perform this action"); } }; @@ -226,7 +230,12 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "POST", url: `${workspaceUsersUrl}/invite`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceAdmin], + preHandler: [ + accessControl, + companyCheck, + checkUserHasCompanyMemberLevel, + checkUserIsWorkspaceMember, + ], preValidation: [fastify.authenticate], schema: inviteWorkspaceUserSchema, handler: workspaceUsersController.invite.bind(workspaceUsersController), @@ -235,7 +244,12 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "DELETE", url: `${workspacePendingUsersUrl}/:email`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceAdmin], + preHandler: [ + accessControl, + companyCheck, + checkUserHasCompanyMemberLevel, + checkUserIsWorkspaceMember, + ], preValidation: [fastify.authenticate], schema: deleteWorkspacePendingUsersSchema, handler: workspaceUsersController.deletePending.bind(workspaceUsersController), @@ -243,8 +257,13 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "GET", - url: `${workspacePendingUsersUrl}/:email`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceAdmin], + url: `${workspacePendingUsersUrl}`, + preHandler: [ + accessControl, + companyCheck, + checkUserHasCompanyMemberLevel, + checkUserIsWorkspaceMember, + ], preValidation: [fastify.authenticate], schema: getWorkspacePendingUsersSchema, handler: workspaceUsersController.listPending.bind(workspaceUsersController), @@ -253,7 +272,12 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "GET", url: `${workspaceInviteTokensUrl}`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceMember], + preHandler: [ + accessControl, + companyCheck, + checkUserIsWorkspaceMember, + checkUserHasCompanyMemberLevel, + ], preValidation: [fastify.authenticate], schema: getWorkspaceInviteTokenSchema, handler: workspaceInviteTokensController.list.bind(workspaceInviteTokensController), @@ -262,7 +286,12 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "POST", url: `${workspaceInviteTokensUrl}`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceMember], + preHandler: [ + accessControl, + companyCheck, + checkUserIsWorkspaceMember, + checkUserHasCompanyMemberLevel, + ], preValidation: [fastify.authenticate], schema: postWorkspaceInviteTokenSchema, handler: workspaceInviteTokensController.save.bind(workspaceInviteTokensController), @@ -271,7 +300,12 @@ const routes: FastifyPluginCallback<{ fastify.route({ method: "DELETE", url: `${workspaceInviteTokensUrl}/:token`, - preHandler: [accessControl, companyCheck, checkUserIsWorkspaceMember], + preHandler: [ + accessControl, + companyCheck, + checkUserIsWorkspaceMember, + checkUserHasCompanyMemberLevel, + ], preValidation: [fastify.authenticate], schema: deleteWorkspaceInviteTokenSchema, handler: workspaceInviteTokensController.delete.bind(workspaceInviteTokensController), diff --git a/twake/backend/node/src/services/workspaces/web/schemas.ts b/twake/backend/node/src/services/workspaces/web/schemas.ts index 7c17691b83..4aa6320590 100644 --- a/twake/backend/node/src/services/workspaces/web/schemas.ts +++ b/twake/backend/node/src/services/workspaces/web/schemas.ts @@ -1,5 +1,5 @@ import { webSocketSchema } from "../../../utils/types"; -import { userObjectSchema } from "../../user/web/schemas"; +import { companyObjectSchema, userObjectSchema } from "../../user/web/schemas"; const workspaceObjectSchema = { type: "object", @@ -244,25 +244,6 @@ export const inviteWorkspaceUserSchema = { }, required: ["invitations"], }, - response: { - "2xx": { - type: "object", - properties: { - resources: { - type: "array", - items: { - type: "object", - properties: { - email: { type: "string" }, - status: { type: "string", enum: ["ok", "error"] }, - message: { type: "string" }, - }, - }, - }, - }, - required: ["resources"], - }, - }, }; export const getWorkspacePendingUsersSchema = { @@ -349,7 +330,12 @@ export const joinInviteTokenSchema = { properties: { company: { type: "object", - properties: { id: { type: "string" }, name: { type: "string" } }, + properties: { + id: { type: "string" }, + name: { type: "string" }, + plan: companyObjectSchema["properties"]["plan"], + stats: companyObjectSchema["properties"]["stats"], + }, }, workspace: { type: "object", diff --git a/twake/backend/node/src/services/workspaces/web/types.ts b/twake/backend/node/src/services/workspaces/web/types.ts index e9656ba395..bdde7a2239 100644 --- a/twake/backend/node/src/services/workspaces/web/types.ts +++ b/twake/backend/node/src/services/workspaces/web/types.ts @@ -1,6 +1,12 @@ import { PaginationQueryParameters, uuid } from "../../../utils/types"; import { WorkspaceUserRole } from "../types"; -import { CompanyUserRole, UserObject } from "../../user/web/types"; +import { + CompanyPlanObject, + CompanyStatsObject, + CompanyUserRole, + UserObject, +} from "../../user/web/types"; +import Company from "../../user/entities/company"; export interface WorkspaceRequest extends WorkspaceBaseRequest { id: uuid; @@ -111,6 +117,7 @@ export interface WorkspaceInviteTokenObject { export interface InviteTokenObject { c: string; w: string; + u: string; t: string; } @@ -121,8 +128,10 @@ export interface WorkspaceJoinByTokenRequest extends WorkspaceBaseRequest { export interface WorkspaceJoinByTokenResponse { company: { - id?: string; - name: string; + id?: Company["id"]; + name: Company["name"]; + stats?: CompanyStatsObject; + plan?: CompanyPlanObject; }; workspace: { id?: string; diff --git a/twake/backend/node/src/twake.ts b/twake/backend/node/src/twake.ts index 63c8eee3c9..b07a221e9d 100644 --- a/twake/backend/node/src/twake.ts +++ b/twake/backend/node/src/twake.ts @@ -1,8 +1,10 @@ import path from "path"; import { TwakePlatform, TwakePlatformConfiguration } from "./core/platform/platform"; +import globalResolver from "./services/global-resolver"; + /** - * Instanciate and start a new TwakePlatform with the given services. + * Instantiate and start a new TwakePlatform with the given services. */ async function run(services: string[] = []): Promise { let platform: TwakePlatform; @@ -16,7 +18,7 @@ async function run(services: string[] = []): Promise { platform = new TwakePlatform(configuration); await platform.init(); await platform.start(); - + await globalResolver.doInit(platform); return platform; } catch (err) { console.error("Will exit process because of: ", err); diff --git a/twake/backend/node/src/utils/company.ts b/twake/backend/node/src/utils/company.ts index b8db5709dd..8ebf3670cb 100644 --- a/twake/backend/node/src/utils/company.ts +++ b/twake/backend/node/src/utils/company.ts @@ -1,3 +1,8 @@ +import { FastifyRequest } from "fastify"; +import { WorkspaceBaseRequest } from "../services/workspaces/web/types"; +import gr from "../services/global-resolver"; +import CompanyUser from "../services/user/entities/company_user"; + export function hasCompanyAdminLevel(role: string): boolean { return role === "admin" || isCompanyOwnerRole(role); } @@ -25,3 +30,20 @@ export function isCompanyMemberRole(role: string): boolean { export function isCompanyGuestRole(role: string): boolean { return role === "guest"; } + +export async function checkUserBelongsToCompany( + userId: string, + companyId: string, +): Promise { + const companyUser = await gr.services.companies.getCompanyUser({ id: companyId }, { id: userId }); + + if (!companyUser) { + const company = await gr.services.companies.getCompany({ id: companyId }); + if (!company) { + throw gr.fastify.httpErrors.notFound(`Company ${companyId} not found`); + } + throw gr.fastify.httpErrors.forbidden("User does not belong to this company"); + } + + return companyUser; +} diff --git a/twake/backend/node/src/utils/counters.ts b/twake/backend/node/src/utils/counters.ts index aba9da3be5..5d29a73412 100644 --- a/twake/backend/node/src/utils/counters.ts +++ b/twake/backend/node/src/utils/counters.ts @@ -1,17 +1,18 @@ import { Column } from "../core/platform/services/database/services/orm/decorators"; import Repository from "../core/platform/services/database/services/orm/repository/repository"; -import { Pagination } from "../core/platform/framework/api/crud-service"; +import { ExecutionContext, Pagination } from "../core/platform/framework/api/crud-service"; import { isMatch } from "lodash"; export const countRepositoryItems = async ( repository: Repository, pk: any, filter: any = {}, + context?: ExecutionContext, ) => { let pagination: Pagination = { limitStr: "100" }; let total = 0; do { - const listResult = await repository.find(pk, { pagination }); + const listResult = await repository.find(pk, { pagination }, context); listResult.filterEntities(a => isMatch(a, filter)); total += listResult.getEntities().length; pagination = listResult.nextPage as Pagination; diff --git a/twake/backend/node/src/utils/handleError.ts b/twake/backend/node/src/utils/handleError.ts index f87b8af0a1..69f830501d 100644 --- a/twake/backend/node/src/utils/handleError.ts +++ b/twake/backend/node/src/utils/handleError.ts @@ -1,10 +1,10 @@ import { FastifyReply } from "fastify"; import { HttpErrorCodes } from "fastify-sensible/lib/httpError"; -import { CrudExeption } from "../core/platform/framework/api/crud-service"; +import { CrudException } from "../core/platform/framework/api/crud-service"; export function handleError(reply: FastifyReply, err: Error): void { - if (err instanceof CrudExeption) { - const crudException: CrudExeption = err; + if (err instanceof CrudException) { + const crudException: CrudException = err; reply.getHttpError(crudException.status as HttpErrorCodes, crudException.message); } else { throw err; diff --git a/twake/backend/node/src/utils/messages.ts b/twake/backend/node/src/utils/messages.ts new file mode 100644 index 0000000000..8aa308061a --- /dev/null +++ b/twake/backend/node/src/utils/messages.ts @@ -0,0 +1,101 @@ +import _ from "lodash"; +import { ThreadExecutionContext } from "../services/messages/types"; +import { getInstance, Message, MessageReaction } from "../services/messages/entities/messages"; + +export function getSubtype( + item: Pick, + context?: ThreadExecutionContext, +): null | "application" | "deleted" | "system" { + //Application request + if (context?.user?.application_id) { + return item.subtype === "application" || item.subtype === "deleted" ? item.subtype : null; + } + //System request + else if (context?.user?.server_request) { + return item.subtype; + } + + //User cannot set a subtype itself + return null; +} + +export function updateMessageReactions( + message: Message, + selectedReactions: string[], + userId: string, +) { + const reactions: { [key: string]: MessageReaction } = {}; + for (const reaction of message.reactions || []) { + reactions[reaction.name] = reaction; + } + for (const reaction of selectedReactions) { + reactions[reaction] = reactions[reaction] || { name: reaction, count: 0, users: [] }; + } + for (const key in reactions) { + if (reactions[key].users.includes(userId)) { + reactions[key].count--; + reactions[key].users = reactions[key].users.filter(u => u != userId); + } + if (selectedReactions.includes(key)) { + reactions[key].count++; + reactions[key].users.push(userId); + } + if (reactions[key].count === 0) { + delete reactions[key]; + } + } + + message.reactions = Object.values(reactions); +} + +export function getDefaultMessageInstance(item: Partial, context: ThreadExecutionContext) { + let instance = getInstance({ + id: undefined, + ephemeral: + (context?.user?.application_id || context?.user?.server_request) && item.ephemeral + ? item.ephemeral + : null, + thread_id: (context?.user?.server_request ? item.thread_id : null) || context.thread.id, + type: context?.user?.server_request && item.type === "event" ? "event" : "message", + subtype: getSubtype({ subtype: item?.subtype || null }, context), + created_at: (context?.user?.server_request ? item.created_at : null) || new Date().getTime(), + user_id: + (context?.user?.server_request || context?.user?.application_id ? item.user_id : null) || + context.user.id, + application_id: + (context?.user?.server_request ? item.application_id : null) || + context?.user?.application_id || + null, + text: item.text || "", + blocks: item.blocks || [], + files: item.files || null, + context: item.context || null, + edited: (context?.user?.server_request ? item.edited : null) || null, //Message cannot be created with edition status + pinned_info: item.pinned_info + ? { + pinned_at: new Date().getTime(), + pinned_by: context.user.id, + } + : null, + quote_message: item.quote_message || null, + reactions: (context?.user?.server_request ? item.reactions : null) || null, // Reactions cannot be set on creation + bookmarks: (context?.user?.server_request ? item.bookmarks : null) || null, + override: + (context?.user?.application_id || context?.user?.server_request) && item.override + ? { + title: item.override.title, + picture: item.override.picture, + } + : null, // Only apps and server can set an override on a message + status: item.status || "sent", + }); + + if (context.user.server_request) { + instance = _.assign( + instance, + _.pickBy(item, v => v !== undefined), + ); + } + + return instance; +} diff --git a/twake/backend/node/src/utils/password-encoder.ts b/twake/backend/node/src/utils/password-encoder.ts index abb0480cd9..df2ce45d50 100644 --- a/twake/backend/node/src/utils/password-encoder.ts +++ b/twake/backend/node/src/utils/password-encoder.ts @@ -1,4 +1,4 @@ -import { CrudExeption } from "../core/platform/framework/api/crud-service"; +import { CrudException } from "../core/platform/framework/api/crud-service"; import crypto from "crypto"; import assert from "assert"; import bcrypt from "bcrypt"; @@ -32,7 +32,7 @@ export default class { public encodePasswordOldWay(raw: string, salt?: string): string { if (this.isPasswordTooLong(raw)) { - throw CrudExeption.badRequest("Invalid password."); + throw CrudException.badRequest("Invalid password."); } const salted = Buffer.from(this.mergePasswordAndSalt(raw, salt)); let digest = crypto.createHash(this.algorithm).update(salted).digest(); diff --git a/twake/backend/node/src/utils/types.ts b/twake/backend/node/src/utils/types.ts index 9e686311e7..f81d0bb5e2 100644 --- a/twake/backend/node/src/utils/types.ts +++ b/twake/backend/node/src/utils/types.ts @@ -2,6 +2,7 @@ * Common types for business services */ +import { WorkspacePrimaryKey } from "../services/workspaces/entities/workspace"; import { Channel as ChannelEntity, ChannelMember, @@ -112,6 +113,7 @@ export interface ResourceEventsPayload { resourcesAfter?: (User | ChannelEntity | ChannelTab | ChannelMember)[]; tab?: ChannelTab; company?: { id: string }; + workspace?: WorkspacePrimaryKey; } export interface PaginationQueryParameters { diff --git a/twake/backend/node/src/utils/users.ts b/twake/backend/node/src/utils/users.ts new file mode 100644 index 0000000000..2b6d4c20c3 --- /dev/null +++ b/twake/backend/node/src/utils/users.ts @@ -0,0 +1,95 @@ +import User from "../services/user/entities/user"; +import { + CompanyShort, + CompanyUserObject, + CompanyUserRole, + CompanyUserStatus, + UserObject, +} from "../services/user/web/types"; +import gr from "../services/global-resolver"; + +export async function formatUser( + user: User, + options?: { includeCompanies?: boolean }, +): Promise { + if (!user) return null; + + let resUser = { + id: user.id, + provider: user.identity_provider, + provider_id: user.identity_provider_id, + email: user.email_canonical, + username: user.username_canonical, + is_verified: Boolean(user.mail_verified), + picture: user.picture, + first_name: user.first_name, + last_name: user.last_name, + full_name: [user.first_name, user.last_name].join(" "), + created_at: user.creation_date, + deleted: Boolean(user.deleted), + status: user.status_icon, + last_activity: user.last_activity, + cache: { companies: user.cache?.companies || [] }, + } as UserObject; + + const userOnline = await gr.services.online.get({ user_id: user.id }); + if (userOnline) { + const { last_seen, is_connected } = userOnline; + + resUser = { + ...resUser, + last_seen, + is_connected, + last_activity: last_seen, + }; + } + + if (options?.includeCompanies) { + const userCompanies = await gr.services.users.getUserCompanies({ id: user.id }); + + const companies = await Promise.all( + userCompanies.map(async uc => { + const company = await gr.services.companies.getCompany({ id: uc.group_id }); + return { + role: uc.role as CompanyUserRole, + status: "active" as CompanyUserStatus, // FIXME: with real status + company: { + id: uc.group_id, + name: company.name, + logo: company.logo, + } as CompanyShort, + } as CompanyUserObject; + }), + ); + + resUser = { + ...resUser, + preferences: { + ...user.preferences, + locale: user.preferences?.language || user.language || "en", + timezone: user.preferences?.timezone || parseInt(user.timezone) || 0, + allow_tracking: user.preferences?.allow_tracking || false, + }, + + companies, + }; + + // Fixme: this is for retro compatibility, should be deleted after march 2022 if mobile did implement it https://github.com/linagora/Twake-Mobile/issues/1265 + resUser.preference = resUser.preferences; + + let name: string = resUser?.username; + if (!name) { + resUser.full_name = "Anonymous"; + } else { + if (resUser.deleted) { + name = "Deleted user"; + } else { + name = [resUser.first_name, resUser.last_name].filter(a => a).join(" "); + name = name || resUser.username; + } + resUser.full_name = name.charAt(0).toUpperCase() + name.slice(1); + } + } + + return resUser; +} diff --git a/twake/backend/node/src/utils/uuid-reducer.ts b/twake/backend/node/src/utils/uuid-reducer.ts new file mode 100644 index 0000000000..b2e5b5b3ff --- /dev/null +++ b/twake/backend/node/src/utils/uuid-reducer.ts @@ -0,0 +1,20 @@ +export const reduceUUID4 = function (id: string) { + if (!id) return undefined; + + return id + .replace(/(.)\1{2,3}/g, "$1i") + .replace(/(.)\1{1,2}/g, "$1h") + .replace(/-/g, "g"); +}; + +export const expandUUID4 = function (id: string) { + if (!id) return undefined; + + return ( + id + .replace(/(.)i/g, "$1$1$1") + .replace(/(.)h/g, "$1$1") + .replace(/[^0-9a-g]/g, "") + .replace(/g/g, "-") || undefined + ); +}; diff --git a/twake/backend/node/src/utils/uuid.ts b/twake/backend/node/src/utils/uuid.ts new file mode 100644 index 0000000000..3ba7e9e65a --- /dev/null +++ b/twake/backend/node/src/utils/uuid.ts @@ -0,0 +1,13 @@ +export function compareTimeuuid(a?: string, b?: string) { + return timeuuidToDate(a || "") - timeuuidToDate(b || ""); +} + +export function timeuuidToDate(time_str: string) { + if (!time_str) { + return 0; + } + var uuid_arr = time_str.split("-"), + // eslint-disable-next-line no-redeclare + time_str = [uuid_arr[2].substring(1), uuid_arr[1], uuid_arr[0]].join(""); + return parseInt(time_str, 16); +} diff --git a/twake/backend/node/src/utils/workspace.ts b/twake/backend/node/src/utils/workspace.ts index ff9a4ee88b..455c381a9d 100644 --- a/twake/backend/node/src/utils/workspace.ts +++ b/twake/backend/node/src/utils/workspace.ts @@ -1,20 +1,14 @@ -import UserServiceAPI from "../services/user/api"; import { User, Workspace } from "./types"; -import Company from "../services/user/entities/company"; -import CompanyUser from "../services/user/entities/company_user"; import WorkspaceUser from "../services/workspaces/entities/workspace_user"; import { hasCompanyAdminLevel } from "./company"; +import gr from "../services/global-resolver"; -export async function isWorkspaceAdmin( - userService: UserServiceAPI, - user?: User, - workspace?: Workspace, -): Promise { +export async function isWorkspaceAdmin(user?: User, workspace?: Workspace): Promise { if (!user || !workspace) { return false; } - const companyUser = await userService.companies.getCompanyUser( + const companyUser = await gr.services.companies.getCompanyUser( { id: workspace.company_id }, { id: user.id }, ); @@ -22,7 +16,7 @@ export async function isWorkspaceAdmin( return true; } - const workspaceUser = await getWorkspaceUser(userService, user, workspace); + const workspaceUser = await getWorkspaceUser(user, workspace); if (!workspaceUser) { return false; @@ -31,24 +25,20 @@ export async function isWorkspaceAdmin( return workspaceUser.role === "moderator"; } -export function hasWorkspaceAdminLevel(role: string): boolean { - return role === "moderator"; +export function hasWorkspaceAdminLevel(role: string, companyRole: string): boolean { + return role === "moderator" || hasCompanyAdminLevel(companyRole); } -export function hasWorkspaceMemberLevel(role: string): boolean { - return role === "member" || hasWorkspaceAdminLevel(role); +export function hasWorkspaceMemberLevel(role: string, companyRole: string): boolean { + return role === "member" || hasWorkspaceAdminLevel(role, companyRole); } -export async function getWorkspaceUser( - userService: UserServiceAPI, - user?: User, - workspace?: Workspace, -): Promise { +export async function getWorkspaceUser(user?: User, workspace?: Workspace): Promise { if (!user || !workspace) { return null; } - const workspaceUser = await userService.workspaces.getUser({ + const workspaceUser = await gr.services.workspaces.getUser({ workspaceId: workspace.workspace_id, userId: user.id, }); @@ -56,23 +46,19 @@ export async function getWorkspaceUser( return workspaceUser; } -export async function getCompanyUser( - userService: UserServiceAPI, - user?: User, - company?: Company, -): Promise { - if (!user || !company) { - return null; - } - - const companyUser = await userService.companies.getCompanyUser( - { - id: company.id, - }, - { - id: user.id, - }, - ); - - return companyUser; -} +// export async function getCompanyUser(user?: User, company?: Company): Promise { +// if (!user || !company) { +// return null; +// } +// +// const companyUser = await gr.services.companies.getCompanyUser( +// { +// id: company.id, +// }, +// { +// id: user.id, +// }, +// ); +// +// return companyUser; +// } diff --git a/twake/backend/node/src/version.ts b/twake/backend/node/src/version.ts index 9e0dbdff2d..e1d6b63fe0 100644 --- a/twake/backend/node/src/version.ts +++ b/twake/backend/node/src/version.ts @@ -1,7 +1,7 @@ export default { - current: /* @VERSION_DETAIL */ "2021.Q4.846", + current: /* @VERSION_DETAIL */ "2022.Q4.1120", minimal: { - web: /* @MIN_VERSION_WEB */ "2021.Q4.846", - mobile: /* @MIN_VERSION_MOBILE */ "2021.Q4.846", + web: /* @MIN_VERSION_WEB */ "2022.Q2.975", + mobile: /* @MIN_VERSION_MOBILE */ "2022.Q2.975", }, }; diff --git a/twake/backend/node/test/client/amqp/message-created.ts b/twake/backend/node/test/client/amqp/message-created.ts deleted file mode 100644 index 770adb7028..0000000000 --- a/twake/backend/node/test/client/amqp/message-created.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Sample client to publish a message in the right channel like when a new message is published in a channel - * From the project root: `./node_modules/.bin/ts-node ./test/client/amqp/message-created.ts` - */ -import { RabbitPubSub } from "../../../src/core/platform/services/pubsub/amqp"; -import config from "../../../src/core/config"; - -const company_id = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; -const workspace_id = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; -const channel_id = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; -const thread_id = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; -const id = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; -const sender = "bcfe2f79-8e81-42a3-b551-3a32d49b2b4c"; - -(async () => { - const rabbit = await RabbitPubSub.get(config.get("pubsub.urls")); - rabbit.publish("message:created", { - data: { - company_id, - workspace_id, - channel_id, - thread_id, - id, - sender, - creation_date: Date.now(), - mentions: { - users: [], - specials: ["all"], - }, - }, - }); -})(); diff --git a/twake/backend/node/test/client/websocket.js b/twake/backend/node/test/client/websocket.js deleted file mode 100644 index b6d54aabee..0000000000 --- a/twake/backend/node/test/client/websocket.js +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable @typescript-eslint/no-var-requires */ -const io = require("socket.io-client"); - -const token = - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjAzODk3MDI3fQ.SLgSEQtsKSgh3k4YEQPmQCVER-_sMkeqrqepMgLT3BE"; -const socket = io.connect("http://localhost:3000", { path: "/socket" }); - -socket.on("connect", () => { - socket - .emit("authenticate", { token }) - .on("authenticated", () => { - console.log("Authenticated in WS"); - // this one fails - socket.emit("realtime:join", { name: "/channels" }); - // this one should be OK - socket.emit("realtime:join", { name: "/channels", token }); - socket.on("realtime:join:error", message => { - // will fire when join does not provide a valid token - console.log("Error on realtime", message); - }); - - socket.on("realtime:join:success", event => { - console.log("Joined room", event.name); - }); - - socket.on("realtime:resource", event => { - console.log(`Resource has been ${event.action}`, event); - }); - }) - .on("unauthorized", err => { - console.log("Unauthorize", err); - }); -}); - -socket.on("disconnected", () => console.log("Disconnected")); diff --git a/twake/backend/node/test/e2e/application/app-create-update.spec.ts b/twake/backend/node/test/e2e/application/app-create-update.spec.ts index 11d9bbd063..8b26d40a37 100644 --- a/twake/backend/node/test/e2e/application/app-create-update.spec.ts +++ b/twake/backend/node/test/e2e/application/app-create-update.spec.ts @@ -1,4 +1,4 @@ -import { beforeAll, describe, expect, it } from "@jest/globals"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { Api } from "../utils.api"; @@ -30,7 +30,7 @@ describe("Applications", () => { }); afterAll(done => { - platform.tearDown().then(done); + platform.tearDown().then(() => done()); }); const publishApp = async id => { @@ -42,7 +42,7 @@ describe("Applications", () => { describe("Create application", function () { it("should 403 if creator is not a company admin", async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; const user = await testDbService.createUser([testDbService.defaultWorkspace()], { companyRole: "member", @@ -54,38 +54,38 @@ describe("Applications", () => { }); it("should 200 on application create", async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; const response = await api.post(`${url}/applications`, payload); expect(response.statusCode).toBe(200); const r = response.resource; - expect(r.company_id).toBe(payload.company_id); + expect(r.company_id).toBe(payload.resource.company_id); expect(!!r.is_default).toBe(false); - expect(r.identity).toMatchObject(payload.identity); - expect(r.access).toMatchObject(payload.access); - expect(r.display).toMatchObject(payload.display); - expect(r.publication).toMatchObject(payload.publication); + expect(r.identity).toMatchObject(payload.resource.identity); + expect(r.access).toMatchObject(payload.resource.access); + expect(r.display).toMatchObject(payload.resource.display); + expect(r.publication).toMatchObject(payload.resource.publication); expect(r.stats).toMatchObject({ - createdAt: expect.any(Number), - updatedAt: expect.any(Number), + created_at: expect.any(Number), + updated_at: expect.any(Number), version: 0, }); expect(r.api).toMatchObject({ - hooksUrl: payload.api.hooksUrl, - allowedIps: payload.api.allowedIps, - privateKey: expect.any(String), + hooks_url: payload.resource.api.hooks_url, + allowed_ips: payload.resource.api.allowed_ips, + private_key: expect.any(String), }); - expect(r.api.privateKey).not.toBe(""); + expect(r.api.private_key).not.toBe(""); const dbData = await appRepo.findOne({ id: response.resource.id }); expect(dbData.api).toMatchObject({ - allowedIps: payload.api.allowedIps, - hooksUrl: payload.api.hooksUrl, - privateKey: expect.any(String), + allowed_ips: payload.resource.api.allowed_ips, + hooks_url: payload.resource.api.hooks_url, + private_key: expect.any(String), }); done(); @@ -95,7 +95,7 @@ describe("Applications", () => { let createdApp: PublicApplicationObject; beforeAll(async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; const response = await api.post(`${url}/applications`, payload); createdApp = response.resource; @@ -116,36 +116,36 @@ describe("Applications", () => { }); it("should 404 if application not found", async done => { - const response = await api.post(`${url}/applications/${uuidv1()}`, postPayload); + const response = await api.post(`${url}/applications/${uuidv1()}`, { resource: postPayload }); expect(response.statusCode).toBe(404); done(); }); describe("Unpublished application", () => { it("should 200 on application update", async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; - payload.is_default = true; - payload.identity.name = "test2"; - payload.api.hooksUrl = "123123"; - payload.access.read = []; - payload.publication.requested = true; + payload.resource.is_default = true; + payload.resource.identity.name = "test2"; + payload.resource.api.hooks_url = "123123"; + payload.resource.access.read = []; + payload.resource.publication.requested = true; const response = await api.post(`${url}/applications/${createdApp.id}`, payload); expect(response.statusCode).toBe(200); const r = response.resource; - expect(r.company_id).toBe(payload.company_id); + expect(r.company_id).toBe(payload.resource.company_id); expect(!!r.is_default).toBe(false); - expect(r.identity).toMatchObject(payload.identity); + expect(r.identity).toMatchObject(payload.resource.identity); - expect(r.access).toMatchObject(payload.access); - expect(r.display).toMatchObject(payload.display); - expect(r.publication).toMatchObject(payload.publication); + expect(r.access).toMatchObject(payload.resource.access); + expect(r.display).toMatchObject(payload.resource.display); + expect(r.publication).toMatchObject(payload.resource.publication); expect(r.stats).toMatchObject({ - createdAt: expect.any(Number), - updatedAt: expect.any(Number), + created_at: expect.any(Number), + updated_at: expect.any(Number), version: 1, }); @@ -154,9 +154,9 @@ describe("Applications", () => { const dbData = await appRepo.findOne({ id: response.resource.id }); expect(dbData.api).toMatchObject({ - allowedIps: payload.api.allowedIps, - hooksUrl: payload.api.hooksUrl, - privateKey: expect.any(String), + allowed_ips: payload.resource.api.allowed_ips, + hooks_url: payload.resource.api.hooks_url, + private_key: expect.any(String), }); done(); @@ -165,7 +165,7 @@ describe("Applications", () => { describe.skip("Published application", () => { beforeAll(async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; const response = await api.post(`${url}/applications`, payload); createdApp = response.resource; await publishApp(createdApp.id); @@ -173,10 +173,10 @@ describe("Applications", () => { }); it("should 200 on update if allowed fields changed", async done => { - const payload = cloneDeep(createdApp) as Application; + const payload = { resource: cloneDeep(createdApp) as Application }; const entity = await appRepo.findOne({ id: createdApp.id }); - payload.api = cloneDeep(entity.api); - payload.publication.requested = true; + payload.resource.api = cloneDeep(entity.api); + payload.resource.publication.requested = true; const response = await api.post(`${url}/applications/${createdApp.id}`, payload); expect(response.statusCode).toBe(200); @@ -188,9 +188,9 @@ describe("Applications", () => { }); it("should 400 on update if not allowed fields changed", async done => { - const payload = cloneDeep(createdApp) as Application; + const payload = { resource: cloneDeep(createdApp) as Application }; const entity = await appRepo.findOne({ id: createdApp.id }); - payload.api = cloneDeep(entity.api); + payload.resource.api = cloneDeep(entity.api); const response = await api.post(`${url}/applications/${createdApp.id}`, payload); expect(response.statusCode).toBe(400); done(); @@ -202,7 +202,7 @@ describe("Applications", () => { let secondApp: PublicApplicationObject; let thirdApp: PublicApplicationObject; beforeAll(async done => { - const payload = cloneDeep(postPayload); + const payload = { resource: cloneDeep(postPayload) }; firstApp = (await api.post(`${url}/applications`, payload)).resource; secondApp = (await api.post(`${url}/applications`, payload)).resource; thirdApp = (await api.post(`${url}/applications`, payload)).resource; @@ -278,8 +278,8 @@ const postPayload = { compatibility: [], }, api: { - hooksUrl: "hooksUrl", - allowedIps: "allowedIps", + hooks_url: "hooks_url", + allowed_ips: "allowed_ips", }, access: { read: ["messages"], diff --git a/twake/backend/node/test/e2e/application/application-events.spec.ts b/twake/backend/node/test/e2e/application/application-events.spec.ts new file mode 100644 index 0000000000..56b3e1e119 --- /dev/null +++ b/twake/backend/node/test/e2e/application/application-events.spec.ts @@ -0,0 +1,119 @@ +import * as crypto from "crypto"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; +import { FastifyInstance, FastifyPluginCallback, FastifyReply, FastifyRequest } from "fastify"; + +import { init, TestPlatform } from "../setup"; +import { TestDbService } from "../utils.prepare.db"; +import { Api } from "../utils.api"; + +import { logger as log } from "../../../src/core/platform/framework"; + +let signingSecret = ""; + +describe("Application events", () => { + const url = "/internal/services/applications/v1"; + let platform: TestPlatform; + let testDbService: TestDbService; + let api: Api; + let appId: string; + + beforeAll(async ends => { + platform = await init(undefined, testAppHookRoute); + + await platform.database.getConnector().drop(); + + testDbService = await TestDbService.getInstance(platform, true); + api = new Api(platform); + + postPayload.company_id = platform.workspace.company_id; + + const createdApplication = await api.post("/internal/services/applications/v1/applications", { + resource: postPayload, + }); + + appId = createdApplication.resource.id; + signingSecret = createdApplication.resource.api.private_key; + + ends(); + + afterAll(done => { + platform.tearDown().then(() => done()); + }); + }); + + it("Should 200 on sending well formed event", async done => { + const payload = { + company_id: platform.workspace.company_id, + workspace_id: platform.workspace.workspace_id, + type: "some type", + name: "name", + content: {}, + }; + + const response = await api.post(`${url}/applications/${appId}/event`, payload); + expect(response.statusCode).toBe(200); + expect(response.resource).toMatchObject({ a: "b" }); + done(); + }); +}); + +const postPayload = { + is_default: false, + company_id: null, + identity: { + code: "code", + name: "name", + icon: "icon", + description: "description", + website: "website", + categories: [], + compatibility: [], + }, + api: { + hooks_url: "http://localhost:3000/test/appHook", + allowed_ips: "allowed_ips", + }, + access: { + read: ["messages"], + write: ["messages"], + delete: ["messages"], + hooks: ["messages"], + }, + display: {}, + publication: { + requested: true, + }, +}; + +const testAppHookRoute = (fastify: FastifyInstance) => { + const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next) => { + fastify.route({ + method: "POST", + url: "/test/appHook", + handler: (request: FastifyRequest, reply: FastifyReply): Promise => { + const signature = request.headers["x-twake-signature"]; + if (!signature) { + reply.status(403); + reply.send({ error: "Signature is missing" }); + return undefined; + } + + const expectedSignature = crypto + .createHmac("sha256", signingSecret) + .update(JSON.stringify(request.body)) + .digest("hex"); + if (expectedSignature != signature) { + reply.status(403); + reply.send({ error: "Wrong signature" }); + return undefined; + } + + log.debug({ signatureMatched: expectedSignature == signature }); + return Promise.resolve({ a: "b" }); + }, + }); + + next(); + }; + fastify.register(routes); +}; diff --git a/twake/backend/node/test/e2e/application/application-login.spec.ts b/twake/backend/node/test/e2e/application/application-login.spec.ts index 9742bf9754..e07e10dd7e 100644 --- a/twake/backend/node/test/e2e/application/application-login.spec.ts +++ b/twake/backend/node/test/e2e/application/application-login.spec.ts @@ -1,18 +1,17 @@ -import { beforeAll, describe, expect, it } from "@jest/globals"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; + import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { Api } from "../utils.api"; import { logger as log } from "../../../src/core/platform/framework"; -import { randomBytes } from "crypto"; import { ApplicationLoginResponse } from "../../../src/services/applicationsapi/web/types"; -import { cloneDeep } from "lodash"; describe("Applications", () => { let platform: TestPlatform; let testDbService: TestDbService; let api: Api; let appId: string; - let privateKey: string; + let private_key: string; let accessToken: ApplicationLoginResponse["access_token"]; beforeAll(async ends => { @@ -23,19 +22,18 @@ describe("Applications", () => { postPayload.company_id = platform.workspace.company_id; - const createdApplication = await api.post( - "/internal/services/applications/v1/applications", - postPayload, - ); + const createdApplication = await api.post("/internal/services/applications/v1/applications", { + resource: postPayload, + }); appId = createdApplication.resource.id; - privateKey = createdApplication.resource.api.privateKey; + private_key = createdApplication.resource.api.private_key; ends(); }); afterAll(done => { - platform.tearDown().then(done); + platform.tearDown().then(() => done()); }); describe("Login", function () { @@ -44,7 +42,7 @@ describe("Applications", () => { const response = await api.post("/api/console/v1/login", { id: appId, - secret: privateKey, + secret: private_key, }); expect(response.statusCode).toBe(200); @@ -127,8 +125,8 @@ const postPayload = { compatibility: [], }, api: { - hooksUrl: "hooksUrl", - allowedIps: "allowedIps", + hooks_url: "hooks_url", + allowed_ips: "allowed_ips", }, access: { read: ["messages"], diff --git a/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts b/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts index 45813ef82d..d66cefe63c 100644 --- a/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts +++ b/twake/backend/node/test/e2e/channels/channels.realtime.spec.ts @@ -1,16 +1,18 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; import { ObjectId } from "mongodb"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import io from "socket.io-client"; import { Channel } from "../../../src/services/channels/entities/channel"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; import { getChannelPath, getPublicRoomName, } from "../../../src/services/channels/services/channel/realtime"; import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { TestPlatform, init } from "../setup"; +import { init, TestPlatform } from "../setup"; import { ChannelUtils, get as getChannelUtils } from "./utils"; +import gr from "../../../src/services/global-resolver"; describe("The Channels Realtime feature", () => { const url = "/internal/services/channels/v1"; @@ -25,7 +27,7 @@ describe("The Channels Realtime feature", () => { "database", "search", "storage", - "pubsub", + "message-queue", "user", "search", "websocket", @@ -113,11 +115,10 @@ describe("The Channels Realtime feature", () => { const roomToken = "twake"; const channelName = new ObjectId().toString(); - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(platform.currentUser.id); channel.name = channelName; - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, channelUtils.getContext({ id: channel.owner }), diff --git a/twake/backend/node/test/e2e/channels/channels.rest.spec.ts b/twake/backend/node/test/e2e/channels/channels.rest.spec.ts index ca29fa4829..6498ae8fe9 100644 --- a/twake/backend/node/test/e2e/channels/channels.rest.spec.ts +++ b/twake/backend/node/test/e2e/channels/channels.rest.spec.ts @@ -1,4 +1,4 @@ -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; import { v1 as uuidv1 } from "uuid"; import { deserialize } from "class-transformer"; import { init, TestPlatform } from "../setup"; @@ -7,9 +7,9 @@ import { ResourceListResponse, ResourceUpdateResponse, User, + Workspace, } from "../../../src/utils/types"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; -import { Channel } from "../../../src/services/channels/entities/channel"; +import { Channel, ChannelMember } from "../../../src/services/channels/entities"; import { ChannelExecutionContext, ChannelVisibility, @@ -19,11 +19,14 @@ import { getPrivateRoomName, getPublicRoomName, } from "../../../src/services/channels/services/channel/realtime"; -import { ChannelMember } from "../../../src/services/channels/entities"; import { ChannelUtils, get as getChannelUtils } from "./utils"; import { TestDbService } from "../utils.prepare.db"; import { ChannelObject } from "../../../src/services/channels/services/channel/types"; import { Api } from "../utils.api"; +import gr from "../../../src/services/global-resolver"; +import { createMessage, e2e_createMessage, e2e_createThread } from "../messages/utils"; +import { ChannelSaveOptions } from "../../../src/services/channels/web/types"; +import { ParticipantObject, Thread } from "../../../src/services/messages/entities/threads"; describe("The /internal/services/channels/v1 API", () => { const url = "/internal/services/channels/v1"; @@ -32,6 +35,12 @@ describe("The /internal/services/channels/v1 API", () => { let testDbService: TestDbService; let api: Api; + beforeAll(async end => { + // platform = await init(); + // await platform.database.getConnector().drop(); + end(); + }); + beforeEach(async () => { platform = await init(); testDbService = new TestDbService(platform); @@ -138,10 +147,9 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should return list of workspace channels", async done => { - const channelService = platform.platform.getProvider("channels"); const channel = new Channel(); channel.name = "Test Channel"; - const creationResult = await channelService.channels.save(channel, {}, getContext()); + const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); const jwtToken = await platform.auth.getJWTToken(); const response = await platform.app.inject({ @@ -167,7 +175,6 @@ describe("The /internal/services/channels/v1 API", () => { result.resources.forEach(r => { expect(r.stats).toMatchObject({ members: 1, - guests: 0, messages: 0, }); }); @@ -180,7 +187,6 @@ describe("The /internal/services/channels/v1 API", () => { await testDbService.createWorkspace(ws0pk); const newUser = await testDbService.createUser([ws0pk]); - const channelService = platform.platform.getProvider("channels"); const channel1 = getChannel(); const channel2 = getChannel(); @@ -188,18 +194,17 @@ describe("The /internal/services/channels/v1 API", () => { channel2.name = "Test Channel2"; const creationResults = await Promise.all([ - channelService.channels.save(channel1, {}, getContext()), - channelService.channels.save(channel2, {}, getContext()), + gr.services.channels.channels.save(channel1, {}, getContext()), + gr.services.channels.channels.save(channel2, {}, getContext()), ]); - await channelService.members.save( + await gr.services.channels.members.save( { channel_id: channel1.id, workspace_id: channel1.workspace_id, company_id: channel1.company_id, user_id: newUser.id, } as ChannelMember, - {}, channelUtils.getChannelContext(channel1, platform.currentUser), ); @@ -231,13 +236,11 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should return pagination information when not all channels are returned", async done => { - const channelService = platform.platform.getProvider("channels"); - await Promise.all( "0123456789".split("").map(name => { const channel = new Channel(); channel.name = name; - return channelService.channels.save(channel, {}, getContext()); + return gr.services.channels.channels.save(channel, {}, getContext()); }), ).catch(() => done(new Error("Failed on creation"))); @@ -268,13 +271,11 @@ describe("The /internal/services/channels/v1 API", () => { it("should be able to paginate over channels from pagination information", async done => { await platform.database.getConnector().drop(); - const channelService = platform.platform.getProvider("channels"); - await Promise.all( "0123456789".split("").map(name => { const channel = new Channel(); channel.name = name; - return channelService.channels.save(channel, {}, getContext()); + return gr.services.channels.channels.save(channel, {}, getContext()); }), ).catch(() => done(new Error("Failed on creation"))); @@ -331,13 +332,11 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should not return pagination information when all channels are returned", async done => { - const channelService = platform.platform.getProvider("channels"); - await Promise.all( "0123456789".split("").map(name => { const channel = new Channel(); channel.name = name; - return channelService.channels.save(channel, {}, getContext()); + return gr.services.channels.channels.save(channel, {}, getContext()); }), ).catch(() => done(new Error("Failed on creation"))); @@ -442,13 +441,13 @@ describe("The /internal/services/channels/v1 API", () => { it("should return the requested channel", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = new Channel(); channel.name = "Test Channel"; channel.company_id = platform.workspace.company_id; channel.workspace_id = platform.workspace.workspace_id; - const creationResult = await channelService.channels.save(channel, {}, getContext()); + const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); const response = await platform.app.inject({ method: "GET", url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${creationResult.entity.id}`, @@ -484,8 +483,6 @@ describe("The /internal/services/channels/v1 API", () => { await testDbService.createDefault(platform); - const channelService = platform.platform.getProvider("channels"); - const channel = new Channel(); channel.name = "Test counters Channel"; channel.company_id = platform.workspace.company_id; @@ -495,7 +492,7 @@ describe("The /internal/services/channels/v1 API", () => { channel.description = "test counters"; channel.channel_group = "my channel group"; - const creationResult = await channelService.channels.save(channel, {}, getContext()); + const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); const channelId = creationResult.entity.id; @@ -522,7 +519,6 @@ describe("The /internal/services/channels/v1 API", () => { expect(resource.stats).toMatchObject({ members: 1, - guests: 0, messages: 0, }); @@ -537,7 +533,7 @@ describe("The /internal/services/channels/v1 API", () => { }); const anotherUserId = uuidv1(); - await channelService.members.addUsersToChannel( + await gr.services.channels.members.addUsersToChannel( [ { id: anotherUserId }, { id: uuidv1() }, @@ -546,17 +542,19 @@ describe("The /internal/services/channels/v1 API", () => { { id: uuidv1() }, ], creationResult.entity, + { + user: { id: platform.currentUser.id }, + }, ); resource = await getChannelREST(channelId); expect(resource.stats).toMatchObject({ members: 6, - guests: 0, messages: 0, }); - await channelService.members.delete( + await gr.services.channels.members.delete( { ...platform.workspace, channel_id: channelId, @@ -569,7 +567,6 @@ describe("The /internal/services/channels/v1 API", () => { expect(resource.stats).toMatchObject({ members: 5, - guests: 0, messages: 0, }); @@ -596,7 +593,6 @@ describe("The /internal/services/channels/v1 API", () => { it("should create a channel", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); const response = await platform.app.inject({ method: "POST", @@ -623,7 +619,7 @@ describe("The /internal/services/channels/v1 API", () => { const res = channelCreateResult.resource; - const createdChannel = await channelService.channels.get({ + const createdChannel = await gr.services.channels.channels.get({ company_id: res.company_id, workspace_id: res.workspace_id, id: res.id, @@ -660,7 +656,6 @@ describe("The /internal/services/channels/v1 API", () => { describe.skip("The POST /companies/:companyId/workspaces/:workspaceId/channels/:id route", () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any async function updateChannel(jwtToken: string, id: string, resource: any): Promise { - const channelService = platform.platform.getProvider("channels"); const response = await platform.app.inject({ method: "POST", url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${id}`, @@ -680,7 +675,11 @@ describe("The /internal/services/channels/v1 API", () => { expect(channelUpdateResult.resource).toBeDefined(); expect(channelUpdateResult.websocket).toBeDefined(); - return await channelService.channels.get({ id }); + return await gr.services.channels.channels.get({ + id, + company_id: platform.workspace.company_id, + workspace_id: platform.workspace.workspace_id, + }); } async function updateChannelFail( @@ -725,11 +724,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should fail when resource is not defined", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -740,11 +738,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the is_default field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -768,11 +765,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the visibility field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -796,11 +792,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the archived field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -823,11 +818,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update all the fields at the same time", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -860,11 +854,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the is_default field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -889,11 +882,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the visibility field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -918,11 +910,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the archived field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -946,11 +937,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update all the fields at the same time", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -983,11 +973,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should not be able to update the is_default field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1006,11 +995,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should not be able to update the visibility field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1029,11 +1017,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should not be able to update the archived field", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1052,11 +1039,10 @@ describe("The /internal/services/channels/v1 API", () => { }); it("should be able to update the 'name', 'description', 'icon' fields", async done => { - const channelService = platform.platform.getProvider("channels"); const jwtToken = await platform.auth.getJWTToken(); const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1127,10 +1113,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should not be able to delete a direct channel", async done => { platform.workspace.workspace_id = "direct"; const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1146,10 +1132,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should be able to delete any channel of the workspace", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1172,10 +1158,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should not be able to delete a direct channel", async done => { platform.workspace.workspace_id = "direct"; const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1191,10 +1177,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should be able to delete the channel", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1216,10 +1202,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should not be able to delete the channel", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1236,10 +1222,10 @@ describe("The /internal/services/channels/v1 API", () => { it("should not be able to delete a direct channel", async done => { platform.workspace.workspace_id = "direct"; const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const channel = getChannel(); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, getContext({ id: channel.owner }), @@ -1254,4 +1240,113 @@ describe("The /internal/services/channels/v1 API", () => { }); }); }); + + describe("The GET /companies/:companyId/workspaces/:workspaceId/recent route", () => { + it("should return list of recent channels for workspace", async done => { + await testDbService.createDefault(platform); + + const channels = []; + + for (let i = 0; i < 5; i++) { + const channel = new Channel(); + channel.name = `Regular Channel ${i}`; + channel.visibility = ChannelVisibility.PUBLIC; + const creationResult = await gr.services.channels.channels.save(channel, {}, getContext()); + channels.push(creationResult.entity); + } + + for (let i = 0; i < 5; i++) { + // const channel = channelUtils.getChannel(); + const directChannelIn = channelUtils.getDirectChannel(); + + const nextUser = await testDbService.createUser( + [{ id: platform.workspace.workspace_id, company_id: platform.workspace.company_id }], + { firstName: "FirstName" + i, lastName: "LastName" + i }, + ); + + const members = [platform.currentUser.id, nextUser.id]; + const directWorkspace: Workspace = { + company_id: platform.workspace.company_id, + workspace_id: ChannelVisibility.DIRECT, + }; + await Promise.all([ + // gr.services.channels.channels.save(channel, {}, getContext()), + gr.services.channels.channels.save( + directChannelIn, + { + members, + }, + { ...getContext(), ...{ workspace: directWorkspace } }, + ), + ]); + channels.push(directChannelIn); + } + + await new Promise(resolve => setTimeout(resolve, 2000)); + + console.log("done awaiting"); + + await e2e_createThread( + platform, + [ + { + company_id: platform.workspace.company_id, + created_at: 0, + created_by: "", + id: channels[2].id, + type: "channel", + workspace_id: platform.workspace.workspace_id, + }, + ], + createMessage({ text: "Initial thread message for regular channel" }), + ); + + await e2e_createThread( + platform, + [ + { + company_id: platform.workspace.company_id, + created_at: 0, + created_by: "", + id: channels[7].id, + type: "channel", + workspace_id: "direct", + }, + ], + createMessage({ text: "Some message" }), + ); + + await gr.services.channels.channels.markAsRead(channels[2], { id: platform.currentUser.id }); + await gr.services.channels.channels.markAsRead(channels[7], { id: platform.currentUser.id }); + + await new Promise(resolve => setTimeout(resolve, 2000)); + + const jwtToken = await platform.auth.getJWTToken(); + + const response = await platform.app.inject({ + method: "GET", + url: `${url}/companies/${platform.workspace.company_id}/channels/recent`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + expect(response.statusCode).toBe(200); + + const result: ResourceListResponse = deserialize( + ResourceListResponse, + response.body, + ); + + console.log(result.resources[0]); + console.log(result.resources.map(a => `${a.name} — ${a.last_activity}`)); + + expect(result.resources.length).toEqual(10); + + expect(result.resources[0].name).toEqual("FirstName2 LastName2"); + expect(result.resources[1].name).toEqual("Regular Channel 2"); + + done(); + }); + }); }); diff --git a/twake/backend/node/test/e2e/channels/channels.search.spec.ts b/twake/backend/node/test/e2e/channels/channels.search.spec.ts new file mode 100644 index 0000000000..e65201a857 --- /dev/null +++ b/twake/backend/node/test/e2e/channels/channels.search.spec.ts @@ -0,0 +1,145 @@ +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { v1 as uuidv1 } from "uuid"; +import { deserialize } from "class-transformer"; +import { init, TestPlatform } from "../setup"; +import { + ResourceGetResponse, + ResourceListResponse, + ResourceUpdateResponse, + User, +} from "../../../src/utils/types"; +import { Channel } from "../../../src/services/channels/entities"; +import { + ChannelExecutionContext, + ChannelVisibility, + WorkspaceExecutionContext, +} from "../../../src/services/channels/types"; +import { ChannelMember } from "../../../src/services/channels/entities"; +import { ChannelUtils, get as getChannelUtils } from "./utils"; +import { TestDbService } from "../utils.prepare.db"; +import { ChannelObject } from "../../../src/services/channels/services/channel/types"; +import { Api } from "../utils.api"; +import gr from "../../../src/services/global-resolver"; + +describe("The /internal/services/channels/v1 API", () => { + const url = "/internal/services/channels/v1"; + let platform: TestPlatform; + let channelUtils: ChannelUtils; + let testDbService: TestDbService; + let api: Api; + + beforeEach(async () => { + platform = await init(); + testDbService = new TestDbService(platform); + api = new Api(platform); + channelUtils = getChannelUtils(platform); + }); + + afterEach(async () => { + await platform?.tearDown(); + platform = null; + }); + + async function testAccess(url, method, done) { + const jwtToken = await platform.auth.getJWTToken(); + const response = await platform.app.inject({ + method, + url, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + expect(response.statusCode).toBe(400); + done(); + } + + function getContext(user?: User): WorkspaceExecutionContext { + return { + workspace: platform.workspace, + user: user || platform.currentUser, + }; + } + + /** + * Get a new channel instance + * + * @param owner will be a random uuidv4 if not defined + */ + function getChannel(owner: string = uuidv1()): Channel { + const channel = new Channel(); + + channel.name = "Test Channel"; + channel.company_id = platform.workspace.company_id; + channel.workspace_id = platform.workspace.workspace_id; + channel.is_default = false; + channel.visibility = ChannelVisibility.PRIVATE; + channel.archived = false; + channel.owner = owner; + + return channel; + } + + async function getChannelREST(channelId: string): Promise { + const response = await api.get( + `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${channelId}`, + ); + + expect(response.statusCode).toEqual(200); + + const channelGetResult: ResourceGetResponse = deserialize( + ResourceGetResponse, + response.body, + ); + + return channelGetResult.resource; + } + + describe("Channels search", () => { + it("Should find channels by name", async done => { + const ws0pk = { id: uuidv1(), company_id: platform.workspace.company_id }; + await testDbService.createWorkspace(ws0pk); + const newUser = await testDbService.createUser([ws0pk]); + + for (let i = 0; i < 10; i++) { + const channel = getChannel(); + channel.name = `test channel ${i}`; + await gr.services.channels.channels.save(channel, {}, getContext()); + + if (i == 0) continue; + await gr.services.channels.members.save( + { + channel_id: channel.id, + workspace_id: channel.workspace_id, + company_id: channel.company_id, + user_id: newUser.id, + } as ChannelMember, + channelUtils.getChannelContext(channel, platform.currentUser), + ); + } + + await new Promise(r => setTimeout(() => r(true), 1000)); + + const jwtToken = await platform.auth.getJWTToken({ sub: newUser.id }); + const response = await platform.app.inject({ + method: "GET", + url: `${url}/companies/${platform.workspace.company_id}/search`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + query: { + q: "test", + }, + }); + + const result: ResourceListResponse = deserialize( + ResourceListResponse, + response.body, + ); + + expect(response.statusCode).toBe(200); + expect(result.resources.length).toEqual(9); + done(); + }); + }); +}); diff --git a/twake/backend/node/test/e2e/channels/direct-channels.spec.ts b/twake/backend/node/test/e2e/channels/direct-channels.spec.ts index 862e93d0b8..8c49e1566a 100644 --- a/twake/backend/node/test/e2e/channels/direct-channels.spec.ts +++ b/twake/backend/node/test/e2e/channels/direct-channels.spec.ts @@ -1,16 +1,18 @@ -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; import { v1 as uuidv1 } from "uuid"; import { deserialize } from "class-transformer"; -import { TestPlatform, init } from "../setup"; -import { ResourceCreateResponse, ResourceListResponse } from "../../../src/utils/types"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { ChannelVisibility } from "../../../src/services/channels/types"; -import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; -import { User, Workspace } from "../../../src/utils/types"; +import { init, TestPlatform } from "../setup"; +import { + ResourceCreateResponse, + ResourceListResponse, + User, + Workspace, +} from "../../../src/utils/types"; +import { Channel } from "../../../src/services/channels/entities"; +import { ChannelVisibility, WorkspaceExecutionContext } from "../../../src/services/channels/types"; import { ChannelUtils, get as getChannelUtils } from "./utils"; import { DirectChannel } from "../../../src/services/channels/entities/direct-channel"; -import { ChannelSaveOptions } from "../../../src/services/channels/web/types"; +import gr from "../../../src/services/global-resolver"; describe("The direct channels API", () => { const url = "/internal/services/channels/v1"; @@ -24,7 +26,7 @@ describe("The direct channels API", () => { "database", "search", "storage", - "pubsub", + "message-queue", "user", "applications", "websocket", @@ -33,7 +35,6 @@ describe("The direct channels API", () => { "storage", "counter", "statistics", - "platform-services", ], }); channelUtils = getChannelUtils(platform); @@ -73,7 +74,6 @@ describe("The direct channels API", () => { }); it("should return list of direct channels the user is member of", async done => { - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(); const directChannelIn = channelUtils.getDirectChannel(); const directChannelNotIn = channelUtils.getDirectChannel(); @@ -84,15 +84,15 @@ describe("The direct channels API", () => { }; const creationResult = await Promise.all([ - channelService.channels.save(channel, {}, getContext()), - channelService.channels.save( + gr.services.channels.channels.save(channel, {}, getContext()), + gr.services.channels.channels.save( directChannelIn, { members, }, { ...getContext(), ...{ workspace: directWorkspace } }, ), - channelService.channels.save( + gr.services.channels.channels.save( directChannelNotIn, { members: [uuidv1(), uuidv1()], @@ -152,7 +152,6 @@ describe("The direct channels API", () => { }); it("should not return direct channels in workspace list", async done => { - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(); const directChannelIn = channelUtils.getDirectChannel(); const directChannelIn2 = channelUtils.getDirectChannel(); @@ -165,10 +164,10 @@ describe("The direct channels API", () => { const creationResult = await Promise.all([ //This channel will automatically contains the requester because it is added automatically in it - channelService.channels.save(channel, {}, getContext()), + gr.services.channels.channels.save(channel, {}, getContext()), //It will contain the currentUser - channelService.channels.save( + gr.services.channels.channels.save( directChannelIn, { members, @@ -177,7 +176,7 @@ describe("The direct channels API", () => { ), //This channel will automatically contains the requester because it is added automatically in it - channelService.channels.save( + gr.services.channels.channels.save( directChannelIn2, { members: [uuidv1(), uuidv1()], @@ -186,7 +185,7 @@ describe("The direct channels API", () => { ), //This channel will not contain the currentUser - channelService.channels.save( + gr.services.channels.channels.save( directChannelNotIn, { members: [uuidv1(), uuidv1()], @@ -220,7 +219,6 @@ describe("The direct channels API", () => { }); it("should not return direct channels in workspace list with mine parameter", async done => { - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(); const channel2 = channelUtils.getChannel(); const directChannelIn = channelUtils.getDirectChannel(); @@ -233,13 +231,13 @@ describe("The direct channels API", () => { await Promise.all([ //This channel will automatically contains the requester because it is added automatically in it - channelService.channels.save(channel, {}, getContext()), + gr.services.channels.channels.save(channel, {}, getContext()), //This channel will not contain currentUser - channelService.channels.save(channel2, {}, getContext({ id: uuidv1() })), + gr.services.channels.channels.save(channel2, {}, getContext({ id: uuidv1() })), //This channel will automatically contains the requester because it is added automatically in it - channelService.channels.save( + gr.services.channels.channels.save( directChannelIn, { members, @@ -247,7 +245,7 @@ describe("The direct channels API", () => { { ...getContext(), ...{ workspace: directWorkspace } }, ), - channelService.channels.save( + gr.services.channels.channels.save( directChannelNotIn, { members: [uuidv1(), uuidv1(), uuidv1()], @@ -283,7 +281,7 @@ describe("The direct channels API", () => { describe("Create direct channel - POST /channels", () => { it("should be able to create a direct channel with members", async done => { const jwtToken = await platform.auth.getJWTToken(); - const channelService = platform.platform.getProvider("channels"); + const members = [uuidv1(), platform.currentUser.id]; const response = await platform.app.inject({ @@ -312,21 +310,21 @@ describe("The direct channels API", () => { expect(channelCreateResult.resource).toBeDefined(); - const createdChannel = await channelService.channels.get({ + const createdChannel = await gr.services.channels.channels.get({ id: channelCreateResult.resource.id, company_id: channelCreateResult.resource.company_id, workspace_id: ChannelVisibility.DIRECT, }); expect(createdChannel).toBeDefined(); - const directChannelEntity = await channelService.channels.getDirectChannel({ + const directChannelEntity = await gr.services.channels.channels.getDirectChannel({ channel_id: createdChannel.id, company_id: createdChannel.company_id, users: DirectChannel.getUsersAsString(members), }); expect(directChannelEntity).toBeDefined(); - const directChannelsInCompany = await channelService.channels.getDirectChannelInCompany( + const directChannelsInCompany = await gr.services.channels.channels.getDirectChannelInCompany( createdChannel.company_id, members, ); diff --git a/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts b/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts index 2d130daa52..eede90a7bf 100644 --- a/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts +++ b/twake/backend/node/test/e2e/channels/skip-channel-members.realtime.spec.ts @@ -1,25 +1,25 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import io from "socket.io-client"; -import { Channel } from "../../../src/services/channels/entities/channel"; -import { ChannelMember } from "../../../src/services/channels/entities/channel-member"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; -import { TestPlatform, init } from "../setup"; +import { Channel, ChannelMember } from "../../../src/services/channels/entities"; +import { init, TestPlatform } from "../setup"; import { ChannelUtils, get as getChannelUtils } from "./utils"; import { getPublicRoomName } from "../../../src/services/channels/services/member/realtime"; import { SaveResult } from "../../../src/core/platform/framework/api/crud-service"; +import gr from "../../../src/services/global-resolver"; describe.skip("The Channels Members Realtime feature", () => { const url = "/internal/services/channels/v1"; let platform: TestPlatform; let socket: SocketIOClient.Socket; let channelUtils: ChannelUtils; - let channelService: ChannelServiceAPI; beforeEach(async () => { platform = await init({ services: [ - "pubsub", + "message-queue", "user", "search", "websocket", @@ -32,7 +32,6 @@ describe.skip("The Channels Members Realtime feature", () => { ], }); channelUtils = getChannelUtils(platform); - channelService = platform.platform.getProvider("channels"); }); afterEach(async () => { @@ -53,7 +52,7 @@ describe.skip("The Channels Members Realtime feature", () => { beforeEach(async () => { channel = channelUtils.getChannel(); - createdChannel = await channelService.channels.save( + createdChannel = await gr.services.channels.channels.save( channel, {}, channelUtils.getContext({ id: channel.owner }), @@ -114,10 +113,9 @@ describe.skip("The Channels Members Realtime feature", () => { const jwtToken = await platform.auth.getJWTToken(); const roomToken = "twake"; - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, channelUtils.getContext({ id: channel.owner }), @@ -129,14 +127,10 @@ describe.skip("The Channels Members Realtime feature", () => { user_id: platform.currentUser.id, } as ChannelMember; - await channelService.members.save( - member, - {}, - { - channel: creationResult.entity, - user: platform.currentUser, - }, - ); + await gr.services.channels.members.save(member, { + channel: creationResult.entity, + user: platform.currentUser, + }); connect(); socket.on("connect", () => { diff --git a/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts b/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts index 250f5f6277..10e6ece9e8 100644 --- a/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts +++ b/twake/backend/node/test/e2e/channels/skip-channel-members.rest.spec.ts @@ -1,24 +1,25 @@ -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { v4 as uuidv4, v1 as uuidv1 } from "uuid"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { v1 as uuidv1, v4 as uuidv4 } from "uuid"; import { deserialize } from "class-transformer"; -import { TestPlatform, init } from "../setup"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; +import { init, TestPlatform } from "../setup"; import { Channel } from "../../../src/services/channels/entities/channel"; import { ChannelMember } from "../../../src/services/channels/entities/channel-member"; -import { ChannelExecutionContext, ChannelVisibility } from "../../../src/services/channels/types"; -import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; +import { + ChannelExecutionContext, + ChannelVisibility, + WorkspaceExecutionContext, +} from "../../../src/services/channels/types"; import { ResourceGetResponse, ResourceListResponse, User } from "../../../src/utils/types"; +import gr from "../../../src/services/global-resolver"; describe.skip("The ChannelMembers REST API", () => { const url = "/internal/services/channels/v1"; let platform: TestPlatform; - let channelService: ChannelServiceAPI; beforeEach(async () => { platform = await init({ services: ["websocket", "webserver", "channels", "auth", "database"], }); - channelService = platform.platform.getProvider("channels"); }); afterEach(async () => { @@ -76,7 +77,7 @@ describe.skip("The ChannelMembers REST API", () => { beforeEach(async () => { channel = getChannel(); - createdChannel = await channelService.channels.save(channel, {}, getWorkspaceContext()); + createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); }); it("should 404 when channel does not exists", done => { @@ -106,9 +107,8 @@ describe.skip("The ChannelMembers REST API", () => { it("should return list of members the user has access to", async done => { const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await channelService.members.save( + const memberCreationResult = await gr.services.channels.members.save( member, - {}, getContext(channel), ); @@ -145,7 +145,7 @@ describe.skip("The ChannelMembers REST API", () => { beforeEach(async () => { channel = getChannel(); - createdChannel = await channelService.channels.save(channel, {}, getWorkspaceContext()); + createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); }); it("should fail when user_id is not defined", async done => { @@ -212,7 +212,7 @@ describe.skip("The ChannelMembers REST API", () => { beforeEach(async () => { channel = getChannel(); - createdChannel = await channelService.channels.save(channel, {}, getWorkspaceContext()); + createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); }); it("should 404 when member does not exist", async done => { @@ -233,9 +233,8 @@ describe.skip("The ChannelMembers REST API", () => { it("should send back member", async done => { const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await channelService.members.save( + const memberCreationResult = await gr.services.channels.members.save( member, - {}, getContext(channel), ); const jwtToken = await platform.auth.getJWTToken(); @@ -271,14 +270,13 @@ describe.skip("The ChannelMembers REST API", () => { beforeEach(async () => { channel = getChannel(); - createdChannel = await channelService.channels.save(channel, {}, getWorkspaceContext()); + createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); }); it("should not be able to update a member when current user is not the member", async done => { const member = getMember(createdChannel.entity, { id: uuidv4() }); - const memberCreationResult = await channelService.members.save( + const memberCreationResult = await gr.services.channels.members.save( member, - {}, getContext(channel), ); const jwtToken = await platform.auth.getJWTToken(); @@ -301,9 +299,8 @@ describe.skip("The ChannelMembers REST API", () => { it("should be able to update member when current user is the member", async done => { const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await channelService.members.save( + const memberCreationResult = await gr.services.channels.members.save( member, - {}, getContext(channel), ); const jwtToken = await platform.auth.getJWTToken(); @@ -322,10 +319,7 @@ describe.skip("The ChannelMembers REST API", () => { expect(response.statusCode).toEqual(200); - const channelMember: ChannelMember = await channelService.members.get( - member, - getContext(channel), - ); + const channelMember: ChannelMember = await gr.services.channels.members.get(member); expect(channelMember).toMatchObject({ channel_id: memberCreationResult.entity.channel_id, @@ -345,7 +339,7 @@ describe.skip("The ChannelMembers REST API", () => { beforeEach(async () => { channel = getChannel(); - createdChannel = await channelService.channels.save(channel, {}, getWorkspaceContext()); + createdChannel = await gr.services.channels.channels.save(channel, {}, getWorkspaceContext()); }); it("should 404 when member does not exist", async done => { @@ -370,30 +364,25 @@ describe.skip("The ChannelMembers REST API", () => { }); it("should not be able to remove the member when current user does not have enough rights", async done => { - const member = getMember(createdChannel.entity, { id: uuidv4() }); - const memberCreationResult = await channelService.members.save( - member, - {}, - getContext(channel), - ); - const jwtToken = await platform.auth.getJWTToken(); - const response = await platform.app.inject({ - method: "DELETE", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, - headers: { - authorization: `Bearer ${jwtToken}`, - }, - }); - - expect(response.statusCode).toEqual(400); - done(); + // const member = getMember(createdChannel.entity, { id: uuidv4() }); + // const memberCreationResult = await gr.services.channels.members.save(member); + // const jwtToken = await platform.auth.getJWTToken(); + // const response = await platform.app.inject({ + // method: "DELETE", + // url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${createdChannel.entity.id}/members/${memberCreationResult.entity.user_id}`, + // headers: { + // authorization: `Bearer ${jwtToken}`, + // }, + // }); + // + // expect(response.statusCode).toEqual(400); + // done(); }); it("should be able to remove the member when current user is the member", async done => { const member = getMember(createdChannel.entity, platform.currentUser); - const memberCreationResult = await channelService.members.save( + const memberCreationResult = await gr.services.channels.members.save( member, - {}, getContext(channel), ); const jwtToken = await platform.auth.getJWTToken(); diff --git a/twake/backend/node/test/e2e/console/console-auth.spec.ts b/twake/backend/node/test/e2e/console/console-auth.spec.ts index da70ad58c8..f542f79561 100644 --- a/twake/backend/node/test/e2e/console/console-auth.spec.ts +++ b/twake/backend/node/test/e2e/console/console-auth.spec.ts @@ -2,14 +2,11 @@ import { afterAll, beforeAll, describe, expect, it as _it, it } from "@jest/glob import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; -import { ConsoleServiceAPI } from "../../../src/services/console/api"; -import { ConsoleOptions, ConsoleType } from "../../../src/services/console/types"; - -let consoleType: ConsoleType = null; +import gr from "../../../src/services/global-resolver"; export const itRemote = (name: string, cb: (a: any) => void) => { _it(name, async done => { - if (consoleType === "remote") { + if (gr.services.console.consoleType === "remote") { cb(done); } else { console.warn(`[skipped]: ${name} (console-mode only)`); @@ -31,13 +28,11 @@ describe("The console API auth", () => { const firstUserPassword = "superPassw0rd"; - let consoleOptions: ConsoleOptions = null; - beforeAll(async ends => { platform = await init({ services: [ "database", - "pubsub", + "message-queue", "search", "applications", "webserver", @@ -69,9 +64,7 @@ describe("The console API auth", () => { // await testDbService.createUser([ws0pk], "member", "member"); // await testDbService.createUser([ws1pk], "member", "member", emailForExistedUser); - const console = platform.platform.getProvider("console"); - consoleOptions = console.consoleOptions; - consoleType = console.consoleType; + await new Promise(r => setTimeout(r, 1000)); ends(); }); diff --git a/twake/backend/node/test/e2e/console/console-hooks.spec.ts b/twake/backend/node/test/e2e/console/console-hooks.spec.ts index 36d9a5e9d3..fadbbec93a 100644 --- a/twake/backend/node/test/e2e/console/console-hooks.spec.ts +++ b/twake/backend/node/test/e2e/console/console-hooks.spec.ts @@ -3,18 +3,15 @@ import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; import { sign as cryptoSign } from "crypto"; -import { ConsoleServiceAPI } from "../../../src/services/console/api"; -import { ConsoleOptions, ConsoleType } from "../../../src/services/console/types"; - +import gr from "../../../src/services/global-resolver"; +import { ConsoleServiceImpl } from "../../../src/services/console/service"; /* THIS TESTS RUNS ONLY FOR THE CONSOLE-MODE (CONSOLE TYPE: REMOTE) */ -let consoleType: ConsoleType = null; - export const it = (name: string, cb: (a: any) => void) => { _it(name, async done => { - if (consoleType === "remote") { + if (gr.services.console.consoleType === "remote") { cb(done); } else { console.warn(`[skipped]: ${name} (console-mode only)`); @@ -37,13 +34,11 @@ describe("The console API hooks", () => { const secret = "ohquoo1fohzeigitochaJeepoowug4Yuqueite6etojieg1oowaeraeshiW8ku8g"; - let consoleOptions: ConsoleOptions = null; - beforeAll(async ends => { platform = await init({ services: [ "database", - "pubsub", + "message-queue", "webserver", "search", "user", @@ -71,9 +66,7 @@ describe("The console API hooks", () => { username: "superman", }); - const console = platform.platform.getProvider("console"); - consoleOptions = console.consoleOptions; - consoleType = console.consoleType; + const console = platform.platform.getProvider("console"); ends(); }); @@ -162,7 +155,9 @@ describe("The console API hooks", () => { payload: getPayload("user_updated", { user: { _id: user.identity_provider_id, - roles: [{ targetCode: companyId, roleCode: "owner" }], + roles: [ + { targetCode: companyId, roleCode: "owner", applications: [{ code: "twake" }] }, + ], email: firstEmail, firstName: "firstName", lastName: "lastName", @@ -193,7 +188,8 @@ describe("The console API hooks", () => { mail_verified: true, timezone: 2, language: "en", - picture: consoleOptions.url.replace(/\/$/, "") + "/avatars/123456.jpg", + picture: + gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/123456.jpg", }); const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); @@ -216,7 +212,9 @@ describe("The console API hooks", () => { payload: getPayload("user_updated", { user: { _id: newUserConsoleId, - roles: [{ targetCode: companyId, roleCode: "admin" }], + roles: [ + { targetCode: companyId, roleCode: "admin", applications: [{ code: "twake" }] }, + ], email: secondEmail, firstName: "consoleFirst", lastName: "consoleSecond", @@ -251,7 +249,7 @@ describe("The console API hooks", () => { identity_provider: "console", identity_provider_id: newUserConsoleId, username_canonical: "consolecreateduser", - picture: consoleOptions.url.replace(/\/$/, "") + "/avatars/5678.jpg", + picture: gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/5678.jpg", }); const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); @@ -273,7 +271,9 @@ describe("The console API hooks", () => { payload: getPayload("user_updated", { user: { _id: newUserConsoleId, - roles: [{ targetCode: companyId, roleCode: "member" }], + roles: [ + { targetCode: companyId, roleCode: "member", applications: [{ code: "twake" }] }, + ], email: thirdEmail, firstName: "superman", lastName: "superman-lastname", @@ -308,7 +308,7 @@ describe("The console API hooks", () => { identity_provider: "console", identity_provider_id: newUserConsoleId, username_canonical: "superman1", - picture: consoleOptions.url.replace(/\/$/, "") + "/avatars/5679.jpg", + picture: gr.services.console.consoleOptions.url.replace(/\/$/, "") + "/avatars/5679.jpg", }); const userRoles = await testDbService.getCompanyUser(companyId, updatedUser.id); diff --git a/twake/backend/node/test/e2e/counters.spec.ts b/twake/backend/node/test/e2e/counters.spec.ts index 843de22290..d26a3cc5c2 100644 --- a/twake/backend/node/test/e2e/counters.spec.ts +++ b/twake/backend/node/test/e2e/counters.spec.ts @@ -2,18 +2,17 @@ // @ts-nocheck import { beforeAll, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "./setup"; -import { DatabaseServiceAPI } from "../../src/core/platform/services/database/api"; import { v1 as uuidv1 } from "uuid"; import { CounterAPI } from "../../src/core/platform/services/counter/types"; import { WorkspaceCounterEntity, WorkspaceCounterPrimaryKey, - WorkspaceCounterType + WorkspaceCounterType, } from "../../src/services/workspaces/entities/workspace_counters"; import { CounterProvider } from "../../src/core/platform/services/counter/provider"; import WorkspaceUser, { getInstance as getWorkspaceUserInstance, - TYPE as WorkspaceUserEntityType + TYPE as WorkspaceUserEntityType, } from "../../src/services/workspaces/entities/workspace_user"; import { countRepositoryItems } from "../../src/utils/counters"; @@ -21,14 +20,15 @@ import { TestDbService } from "./utils.prepare.db"; import { ChannelCounterEntity, ChannelCounterPrimaryKey, - ChannelUserCounterType -} from "../../src/services/channels/entities/channel_counters"; + ChannelUserCounterType, +} from "../../src/services/channels/entities/channel-counters"; import { ChannelMemberType } from "../../src/services/channels/types"; import { getMemberOfChannelInstance, MemberOfChannel } from "../../src/services/channels/entities"; +import gr from "../../src/services/global-resolver"; describe("Counters implementation", () => { let platform: TestPlatform; - let database: DatabaseServiceAPI; + // let database: DatabaseServiceAPI; let counterApi: CounterAPI; let testDbService: TestDbService; @@ -37,8 +37,7 @@ describe("Counters implementation", () => { testDbService = new TestDbService(platform); - database = platform.platform.getProvider("database"); - await platform.database.getConnector().drop(); + await gr.database.getConnector().drop(); counterApi = platform.platform.getProvider("counter"); expect(counterApi).toBeTruthy(); @@ -66,12 +65,6 @@ describe("Counters implementation", () => { WorkspaceUser, ); - counter.reviseCounter(async (pk: WorkspaceCounterPrimaryKey) => { - if (pk.counter_type == "members") { - return countRepositoryItems(workspaceUserRepository, { workspace_id: pk.id }); - } - }, 4); - await workspaceUserRepository.save( getWorkspaceUserInstance({ workspaceId: counterPk.id, @@ -127,6 +120,17 @@ describe("Counters implementation", () => { it("Revising counter", async done => { // Subtracting 2 + const workspaceUserRepository = await testDbService.getRepository( + WorkspaceUserEntityType, + WorkspaceUser, + ); + + counter.setReviseCallback(async (pk: WorkspaceCounterPrimaryKey) => { + if (pk.counter_type == "members") { + return countRepositoryItems(workspaceUserRepository, { workspace_id: pk.id }); + } + }, 4); + await counter.increase(counterPk, 1); const val = await counter.get(counterPk); expect(val).toEqual(1); @@ -154,16 +158,6 @@ describe("Counters implementation", () => { MemberOfChannel, ); - counter.reviseCounter(async (pk: ChannelCounterPrimaryKey) => { - if (pk.counter_type == ChannelUserCounterType.MEMBERS) { - return countRepositoryItems( - memberOfChannelRepository, - { channel_id: pk.id, company_id: pk.company_id, workspace_id: pk.workspace_id }, - { type: ChannelMemberType.MEMBER }, - ); - } - }, 4); - await memberOfChannelRepository.save( getMemberOfChannelInstance({ company_id: counterPk.company_id, @@ -173,30 +167,6 @@ describe("Counters implementation", () => { }), ); - // const channelMemberRepository = await testDbService.getRepository( - // "user_channels", - // ChannelMember, - // ); - // - // counter.reviseCounter(async (pk: ChannelCounterPrimaryKey) => { - // if (pk.counter_type == ChannelUserCounterType.MEMBERS) { - // return countRepositoryItems( - // channelMemberRepository, - // { channel_id: pk.id }, - // { type: ChannelMemberType.MEMBER }, - // ); - // } - // }, 4); - // - // await channelMemberRepository.save( - // getChannelMemberInstance({ - // company_id: uuidv1(), - // workspace_id: uuidv1(), - // channel_id: counterPk.id, - // user_id: uuidv1(), - // }), - // ); - expect(counter).toBeTruthy(); ends(); @@ -244,6 +214,21 @@ describe("Counters implementation", () => { it("Revising counter", async done => { // Subtracting 2 + const memberOfChannelRepository = await testDbService.getRepository( + "channel_members", + MemberOfChannel, + ); + + counter.setReviseCallback(async (pk: ChannelCounterPrimaryKey) => { + if (pk.counter_type == ChannelUserCounterType.MEMBERS) { + return countRepositoryItems( + memberOfChannelRepository, + { channel_id: pk.id, company_id: pk.company_id, workspace_id: pk.workspace_id }, + { type: ChannelMemberType.MEMBER }, + ); + } + }, 4); + await counter.increase(counterPk, 1); const val = await counter.get(counterPk); expect(val).toEqual(1); diff --git a/twake/backend/node/test/e2e/files/assets/sample.mp4 b/twake/backend/node/test/e2e/files/assets/sample.mp4 new file mode 100644 index 0000000000..7936dc0909 Binary files /dev/null and b/twake/backend/node/test/e2e/files/assets/sample.mp4 differ diff --git a/twake/backend/node/test/e2e/files/files.spec.ts b/twake/backend/node/test/e2e/files/files.spec.ts index 3ee326adb7..d37ef1b4df 100644 --- a/twake/backend/node/test/e2e/files/files.spec.ts +++ b/twake/backend/node/test/e2e/files/files.spec.ts @@ -1,19 +1,23 @@ import "reflect-metadata"; -import { describe, it, beforeAll, afterAll, expect } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; import { ResourceUpdateResponse } from "../../../src/utils/types"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import fs from "fs"; import { File } from "../../../src/services/files/entities/file"; import { deserialize } from "class-transformer"; import formAutoContent from "form-auto-content"; +import { MessageFile } from "../../../src/services/messages/entities/message-files"; +import { createMessage, e2e_createThread } from "../messages/utils"; -describe("The Files feature", () => { +describe.skip("The Files feature", () => { const url = "/internal/services/files/v1"; let platform: TestPlatform; beforeAll(async () => { platform = await init({ - services: ["webserver", "database", "storage", "pubsub", "files", "previews"], + services: ["webserver", "database", "storage", "message-queue", "files", "previews"], }); }); @@ -30,10 +34,11 @@ describe("The Files feature", () => { "assets/sample.pdf", "assets/sample.doc", "assets/sample.zip", + "assets/sample.mp4", ].map(p => `${__dirname}/${p}`); - const thumbnails = [1, 1, 2, 5, 0]; + const thumbnails = [1, 1, 2, 5, 0, 1]; - it(`should save file and generate previews`, async done => { + it("should save file and generate previews", async done => { for (const i in files) { const file = files[i]; diff --git a/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts b/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts new file mode 100644 index 0000000000..c1003bdf72 --- /dev/null +++ b/twake/backend/node/test/e2e/messages/messages.files.search.spec.ts @@ -0,0 +1,165 @@ +import "reflect-metadata"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +import { createMessage, createParticipant, e2e_createThread } from "./utils"; +import { MessageFile } from "../../../src/services/messages/entities/message-files"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import fs from "fs"; +import formAutoContent from "form-auto-content"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import uuid, { v1 } from "node-uuid"; +import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; +import gr from "../../../src/services/global-resolver"; +import User from "../../../src/services/user/entities/user"; +import { WorkspaceExecutionContext } from "../../../src/services/channels/types"; + +describe("Search files", () => { + const filesUrl = "/internal/services/files/v1"; + const messagesUrl = "/internal/services/messages/v1"; + let platform: TestPlatform; + let channelUtils: ChannelUtils; + + beforeAll(async () => { + platform = await init({ + services: ["webserver", "database", "storage", "message-queue", "files", "previews"], + }); + await platform.database.getConnector().drop(); + channelUtils = getChannelUtils(platform); + }); + + afterAll(async done => { + await platform?.tearDown(); + platform = null; + done(); + }); + + const files = [ + "../files/assets/sample.png", + "../files/assets/sample.gif", + "../files/assets/sample.pdf", + "../files/assets/sample.doc", + "../files/assets/sample.zip", + ].map(p => `${__dirname}/${p}`); + + function getContext(user?: User): WorkspaceExecutionContext { + return { + workspace: platform.workspace, + user: user || platform.currentUser, + }; + } + + it("should return uploaded files", async done => { + let channel = channelUtils.getChannel(); + channel = (await gr.services.channels.channels.save(channel, {}, getContext())).entity; + const channelId = channel.id; + + const uploadedFiles = []; + for (const i in files) { + const file = files[i]; + + const form = formAutoContent({ file: fs.createReadStream(file) }); + form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; + + const uploadedFile = await platform.app.inject({ + method: "POST", + url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, + ...form, + }); + + const resource = uploadedFile.json().resource; + + const messageFile: Partial = { + id: uuid.v1(), + company_id: platform.workspace.company_id, + metadata: { + source: "internal", + external_id: { + company_id: platform.workspace.company_id, + id: resource.id, + }, + ...resource.metadata, + }, + }; + + await e2e_createThread( + platform, + [ + createParticipant( + { + type: "channel", + id: channelId, + }, + platform, + ), + ], + createMessage({ text: "Some message", files: [messageFile] }), + ); + + uploadedFiles.push(uploadedFile.json().resource); + } + + await new Promise(r => setTimeout(r, 2000)); + + let resources = await search("sample"); + expect(resources.length).toEqual(5); + + resources = await search("sample", { extension: "png" }); + expect(resources.length).toEqual(1); + + resources = await search("sample", { is_file: true }); + expect(resources.length).toEqual(3); + + resources = await search("sample", { is_media: true }); + expect(resources.length).toEqual(2); + + resources = await search("sam"); + expect(resources.length).toEqual(5); + + done(); + }); + + async function search( + searchString: string, + options?: { + company_id?: string; + workspace_id?: string; + channel_id?: string; + limit?: number; + sender?: string; + is_file?: boolean; + is_media?: boolean; + extension?: string; + }, + ): Promise { + const jwtToken = await platform.auth.getJWTToken(); + + const query: any = options || {}; + + const response = await platform.app.inject({ + method: "GET", + url: `${messagesUrl}/companies/${platform.workspace.company_id}/files/search`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + query: { + ...query, + q: searchString, + }, + }); + + expect(response.statusCode).toBe(200); + const json = response.json(); + expect(json).toMatchObject({ resources: expect.any(Array) }); + const resources = json.resources; + return resources; + } +}); + +function getContext(platform: TestPlatform) { + return { + company: { id: platform.workspace.company_id }, + user: { id: platform.currentUser.id }, + }; +} diff --git a/twake/backend/node/test/e2e/messages/messages.files.spec.ts b/twake/backend/node/test/e2e/messages/messages.files.spec.ts index 944e371d31..01b50f794a 100644 --- a/twake/backend/node/test/e2e/messages/messages.files.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.files.spec.ts @@ -1,14 +1,21 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; import { ResourceUpdateResponse } from "../../../src/utils/types"; import { deserialize } from "class-transformer"; import { Thread } from "../../../src/services/messages/entities/threads"; import { createMessage, e2e_createThread } from "./utils"; import { MessageFile } from "../../../src/services/messages/entities/message-files"; import { Message } from "../../../src/services/messages/entities/messages"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import fs from "fs"; +import formAutoContent from "form-auto-content"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import uuid, { v1 } from "node-uuid"; -describe("The Messages Threads feature", () => { +describe("The Messages Files feature", () => { const url = "/internal/services/messages/v1"; let platform: TestPlatform; @@ -20,7 +27,7 @@ describe("The Messages Threads feature", () => { "applications", "search", "storage", - "pubsub", + "message-queue", "user", "search", "files", @@ -43,11 +50,14 @@ describe("The Messages Threads feature", () => { describe("On user send files", () => { it("did add the files when full information is given (external source)", async done => { const file: MessageFile = { + cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, + company_id: "", + created_at: 0, + id: "", metadata: { source: "linshare", external_id: "1234", name: "My LinShare File", - type: "image/png", thumbnails: [], }, }; @@ -73,21 +83,27 @@ describe("The Messages Threads feature", () => { it("did not deduplicate files", async done => { const file: MessageFile = { + cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, + company_id: "", + created_at: 0, + id: "", metadata: { source: "linshare", external_id: "1234", name: "My LinShare File", - type: "image/png", thumbnails: [], }, }; const file2: MessageFile = { + cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, + company_id: "", + created_at: 0, + id: "", metadata: { source: "linshare2", external_id: "5678", name: "My LinShare 2 File", - type: "image/png", thumbnails: [], }, }; @@ -130,6 +146,216 @@ describe("The Messages Threads feature", () => { }); }); +describe("List user files", () => { + const filesUrl = "/internal/services/files/v1"; + const messagesUrl = "/internal/services/messages/v1"; + let platform: TestPlatform; + + beforeAll(async () => { + platform = await init({ + services: ["webserver", "database", "storage", "message-queue", "files", "previews"], + }); + await platform.database.getConnector().drop(); + }); + + afterAll(async done => { + await platform?.tearDown(); + platform = null; + done(); + }); + + const files = [ + "../files/assets/sample.png", + "../files/assets/sample.gif", + "../files/assets/sample.pdf", + "../files/assets/sample.doc", + "../files/assets/sample.zip", + ].map(p => `${__dirname}/${p}`); + + it("should return uploaded files", async done => { + const jwtToken = await platform.auth.getJWTToken(); + + const uploadedFiles = []; + + for (const i in files) { + const file = files[i]; + + const form = formAutoContent({ file: fs.createReadStream(file) }); + form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; + + const uploadedFile = await platform.app.inject({ + method: "POST", + url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, + ...form, + }); + + expect(uploadedFile.statusCode).toBe(200); + + const resource = uploadedFile.json().resource; + + const messageFile: MessageFile = { + cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, + created_at: 0, + id: uuid.v1(), + company_id: platform.workspace.company_id, + metadata: { + source: "internal", + external_id: { + company_id: platform.workspace.company_id, + id: resource.id, + }, + ...resource.metadata, + }, + }; + + await e2e_createThread( + platform, + [], + createMessage({ text: "Some message", files: [messageFile] }), + ); + + uploadedFiles.push(uploadedFile.json().resource); + } + + function checkResource(resource) { + expect(resource).toMatchObject({ + company_id: expect.any(String), + id: expect.any(String), + created_at: expect.any(Number), + metadata: expect.any(Object), + }); + } + + let response = await platform.app.inject({ + method: "GET", + url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_upload&limit=3`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + expect(response.statusCode).toBe(200); + + let resources = response.json().resources; + expect(resources.length).toBe(3); + + resources.forEach(checkResource); + + const nextPageToken = response.json().next_page_token; + + response = await platform.app.inject({ + method: "GET", + url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_upload&page_token=${nextPageToken}limit=100`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + expect(response.statusCode).toBe(200); + + resources = response.json().resources; + expect(resources.length).toBe(5); + + expect(response.json().resources[0]).toMatchObject({ + company_id: expect.any(String), + id: expect.any(String), + created_at: expect.any(Number), + metadata: expect.any(Object), + user: expect.any(Object), + context: expect.any(Object), + }); + + resources.forEach(checkResource); + + done(); + }); + + it("should return downloaded files", async done => { + const jwtToken = await platform.auth.getJWTToken({ sub: v1() }); + const uploadedFiles = []; + for (const i in files) { + const file = files[i]; + + const form = formAutoContent({ file: fs.createReadStream(file) }); + form.headers["authorization"] = `Bearer ${await platform.auth.getJWTToken()}`; + + const uploadedFile = await platform.app.inject({ + method: "POST", + url: `${filesUrl}/companies/${platform.workspace.company_id}/files?thumbnail_sync=1`, + ...form, + }); + + const resource = uploadedFile.json().resource; + + const messageFile: MessageFile = { + cache: { channel_id: "", company_id: "", user_id: "", workspace_id: "" }, + created_at: 0, + id: uuid.v1(), + company_id: platform.workspace.company_id, + metadata: { + source: "internal", + external_id: { + company_id: platform.workspace.company_id, + id: resource.id, + }, + ...resource.metadata, + }, + }; + + const thread = await e2e_createThread( + platform, + [], + createMessage({ text: "Some message", files: [messageFile] }), + ); + + uploadedFiles.push(uploadedFile.json().resource); + + await platform.app.inject({ + method: "POST", + url: `${messagesUrl}/companies/${platform.workspace.company_id}/threads/${ + thread.json().resource.message.thread_id + }/messages/${thread.json().resource.message.id}/download/${ + thread.json().resource.message.files[0].id + }`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + const response = await platform.app.inject({ + method: "GET", + url: `${messagesUrl}/companies/${platform.workspace.company_id}/files?type=user_download`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + expect(response.statusCode).toBe(200); + + expect(response.json().resources.length).toBe(5); + + expect(response.json().resources[0]).toMatchObject({ + company_id: expect.any(String), + id: expect.any(String), + created_at: expect.any(Number), + metadata: expect.any(Object), + user: expect.any(Object), + context: expect.any(Object), + }); + + done(); + }); +}); + function getContext(platform: TestPlatform) { return { company: { id: platform.workspace.company_id }, diff --git a/twake/backend/node/test/e2e/messages/messages.messages.spec.ts b/twake/backend/node/test/e2e/messages/messages.messages.spec.ts index 28bcdb3463..2d30b256c1 100644 --- a/twake/backend/node/test/e2e/messages/messages.messages.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.messages.spec.ts @@ -1,25 +1,51 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; -import { ResourceListResponse, ResourceUpdateResponse } from "../../../src/utils/types"; +import { afterEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +import { + ResourceListResponse, + ResourceUpdateResponse, + User, + Workspace, +} from "../../../src/utils/types"; import { deserialize } from "class-transformer"; -import { Thread } from "../../../src/services/messages/entities/threads"; -import { createMessage, e2e_createMessage, e2e_createThread } from "./utils"; +import { ParticipantObject, Thread } from "../../../src/services/messages/entities/threads"; +import { + createMessage, + createParticipant, + e2e_createChannel, + e2e_createMessage, + e2e_createThread, +} from "./utils"; import { Message } from "../../../src/services/messages/entities/messages"; import { v1 as uuidv1 } from "uuid"; +import { MessageWithReplies } from "../../../src/services/messages/types"; +import { TestDbService } from "../utils.prepare.db"; +import gr from "../../../src/services/global-resolver"; +import { ChannelVisibility, WorkspaceExecutionContext } from "../../../src/services/channels/types"; +import { ChannelSaveOptions } from "../../../src/services/channels/web/types"; +import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; describe("The Messages feature", () => { const url = "/internal/services/messages/v1"; let platform: TestPlatform; + let testDbService: TestDbService; + let channelUtils: ChannelUtils; - beforeEach(async () => { + function getContext(user?: User): WorkspaceExecutionContext { + return { + workspace: platform.workspace, + user: user || platform.currentUser, + }; + } + + beforeAll(async () => { platform = await init({ services: [ "webserver", "database", "search", "storage", - "pubsub", + "message-queue", "applications", "user", "websocket", @@ -35,6 +61,9 @@ describe("The Messages feature", () => { "platform-services", ], }); + await gr.database.getConnector().drop(); + + channelUtils = getChannelUtils(platform); }); afterEach(async () => { @@ -75,92 +104,96 @@ describe("The Messages feature", () => { expect(listResponse.statusCode).toBe(200); expect(listResult.resources.length).toBe(3); }); + }); - it("should move the message in threads", async () => { - const userA = uuidv1(); - const userB = uuidv1(); - const userC = uuidv1(); - - const thread1Request = await e2e_createThread( - platform, - [], - createMessage({ text: "Message A in thread 1", user_id: userA }), - ); - const thread1Result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - thread1Request.body, - ); - const thread1: Thread = thread1Result.resource; - - const thread2Request = await e2e_createThread( - platform, - [], - createMessage({ text: "Message B in thread 2", user_id: userB }), - ); - const thread2Result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - thread2Request.body, - ); - const thread2: Thread = thread2Result.resource; - - const messageCRequest = await e2e_createMessage( - platform, - thread1.id, - createMessage({ text: "Message C in thread 1", user_id: userC }), - ); - const messageCResult: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - messageCRequest.body, - ); - const messageC: Message = messageCResult.resource; - - const messageCAfterMoveRequest = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${thread2.id}/messages/${messageC.id}`, - headers: { - authorization: `Bearer ${await platform.auth.getJWTToken({ sub: userA })}`, - }, - payload: { - resource: messageC, - options: { - previous_thread: thread1.id, + describe("Inbox", () => { + it("Should get recent user messages", async done => { + const directChannelIn = channelUtils.getDirectChannel(); + const members = [platform.currentUser.id, uuidv1()]; + const directWorkspace: Workspace = { + company_id: platform.workspace.company_id, + workspace_id: ChannelVisibility.DIRECT, + }; + + await Promise.all([ + gr.services.channels.channels.save( + directChannelIn, + { + members, }, + { ...getContext(), ...{ workspace: directWorkspace } }, + ), + ]); + + const recipient: ParticipantObject = { + created_at: 0, + created_by: "", + type: "channel", + company_id: directChannelIn.company_id, + workspace_id: "direct", + id: directChannelIn.id, + }; + + for (let i = 0; i < 6; i++) { + const response = await e2e_createThread( + platform, + [recipient], + createMessage({ text: `Initial thread message ${i}` }), + ); + const result: ResourceUpdateResponse = deserialize( + ResourceUpdateResponse, + response.body, + ); + const threadId = result.resource.id; + + const replies = []; + for (let j = 0; j < 3; j++) { + replies.push( + e2e_createMessage( + platform, + threadId, + createMessage({ text: `Reply ${j} to message ${i}` }), + ), + ); + } + await Promise.all(replies); + } + + const jwtToken = await platform.auth.getJWTToken({ sub: members[0] }); + const response = await platform.app.inject({ + method: "GET", + url: `${url}/companies/${platform.workspace.company_id}/inbox?limit=5`, + headers: { + authorization: `Bearer ${jwtToken}`, }, }); - const messageCAfterMoveResult: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - messageCAfterMoveRequest.body, - ); - const messageCAfterMove: Message = messageCAfterMoveResult.resource; - //See if message was moved correctly to the new thread - expect(messageCAfterMove.user_id).toBe(userC); - expect(messageCAfterMove.thread_id).toBe(thread2.id); + expect(response.statusCode).toEqual(200); - const messageCAfterMove2Request = await platform.app.inject({ - method: "POST", - url: `${url}/companies/${platform.workspace.company_id}/threads/${messageC.id}/messages/${messageC.id}`, - headers: { - authorization: `Bearer ${await platform.auth.getJWTToken({ sub: userA })}`, - }, - payload: { - resource: messageC, - options: { - previous_thread: thread2.id, - }, - }, - }); - const messageCAfterMove2Result: ResourceUpdateResponse = deserialize( - ResourceUpdateResponse, - messageCAfterMove2Request.body, + const inbox: ResourceListResponse = deserialize( + ResourceListResponse, + response.body, ); - const messageCAfter2Move: Message = messageCAfterMove2Result.resource; - //See if message was moved correctly to new standalone thread - expect(messageCAfter2Move.user_id).toBe(userC); - expect(messageCAfter2Move.thread_id).toBe(messageCAfter2Move.id); + expect(inbox.resources.length).toEqual(5); + + for (const resource of inbox.resources) { + expect(resource).toMatchObject({ + id: expect.any(String), + thread_id: expect.any(String), + created_at: expect.any(Number), + updated_at: expect.any(Number), + user_id: platform.currentUser.id, + application_id: null, + text: expect.any(String), + cache: { + company_id: directChannelIn.company_id, + channel_id: directChannelIn.id, + }, + }); + } - //TODO check counts + done(); }); }); }); diff --git a/twake/backend/node/test/e2e/messages/messages.search.spec.ts b/twake/backend/node/test/e2e/messages/messages.search.spec.ts index 4be038f024..f1c3afdef2 100644 --- a/twake/backend/node/test/e2e/messages/messages.search.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.search.spec.ts @@ -1,33 +1,27 @@ -import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; -import { createMessage, e2e_createMessage, e2e_createThread } from "./utils"; +import { createMessage, e2e_createChannel, e2e_createMessage, e2e_createThread } from "./utils"; import { ResourceUpdateResponse } from "../../../src/utils/types"; import { ParticipantObject, Thread } from "../../../src/services/messages/entities/threads"; import { deserialize } from "class-transformer"; import { Channel } from "../../../src/services/channels/entities"; -import { - ChannelUtils, - get as getChannelUtils, - getMemberUtils, - ChannelMemberUtils, -} from "../channels/utils"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; -import { assign } from "lodash"; +import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; +import { MessageFile } from "../../../src/services/messages/entities/message-files"; +import gr from "../../../src/services/global-resolver"; describe("The /messages API", () => { const url = "/internal/services/messages/v1"; let platform: TestPlatform; let channelUtils: ChannelUtils; - let channelService; - beforeEach(async ends => { + beforeAll(async ends => { platform = await init({ services: [ "database", "search", - "pubsub", + "message-queue", "websocket", "webserver", "user", @@ -44,30 +38,36 @@ describe("The /messages API", () => { await platform.database.getConnector().drop(); channelUtils = getChannelUtils(platform); - channelService = platform.platform.getProvider("channels"); + + const testDbService = new TestDbService(platform); + await testDbService.createCompany(platform.workspace.company_id); + + const workspacePk = { + id: platform.workspace.workspace_id, + company_id: platform.workspace.company_id, + }; + + const workspacePk2 = { + id: uuidv1(), + company_id: uuidv1(), + }; + await testDbService.createWorkspace(workspacePk); + + const user = await testDbService.createUser([workspacePk], {}); + + platform.currentUser.id = user.id; ends(); }); - afterEach(async ends => { + afterAll(async ends => { platform && (await platform.tearDown()); platform = null; ends(); }); describe("The GET /messages/?search=... route", () => { - it("Should find the searched users", async done => { - const testDbService = new TestDbService(platform); - await testDbService.createCompany(platform.workspace.company_id); - const workspacePk = { - id: platform.workspace.workspace_id, - company_id: platform.workspace.company_id, - }; - const workspacePk2 = { - id: uuidv1(), - company_id: uuidv1(), - }; - await testDbService.createWorkspace(workspacePk); + it("Should find the searched messages", async done => { // await testDbService.createWorkspace(workspacePk2); const channel = await createChannel(); @@ -85,7 +85,7 @@ describe("The /messages API", () => { const secondThreadId = await createThread("Another thread", [participant]); await createReply(secondThreadId, "First reply of second thread"); - await createReply(secondThreadId, "Second reply of second thread"); + await createReply(secondThreadId, "Second reply of second thread is also a message"); //Wait for indexation to happen await new Promise(r => setTimeout(r, 3000)); @@ -93,10 +93,6 @@ describe("The /messages API", () => { let resources = await search("Reply"); expect(resources.length).toEqual(4); - resources.forEach(resource => { - expect(resource.last_replies.length).toEqual(1); - }); - resources = await search("fdfsd"); expect(resources.length).toEqual(0); @@ -109,27 +105,112 @@ describe("The /messages API", () => { resources = await search("another"); expect(resources.length).toEqual(1); - resources.forEach(resource => { - expect(resource.last_replies.length).toEqual(0); + resources = await search("also"); + expect(resources.length).toEqual(1); + + resources = await search("of"); + expect(resources.length).toEqual(4); + + resources = await search("a"); + + //sleep 1s + await new Promise(r => setTimeout(r, 2000)); + + expect(resources.length).toEqual(1); + + done(); + }); + it("Filter out messages from channels we are not member of", async done => { + const anotherUserId = uuidv1(); + const channel = await e2e_createChannel(platform, [platform.currentUser.id, anotherUserId]); + const anotherChannel = await e2e_createChannel(platform, [anotherUserId], anotherUserId); //Test user is not the owner + + const participant = { + type: "channel", + id: channel.resource.id, + company_id: channel.resource.company_id, + workspace_id: channel.resource.workspace_id, + } as ParticipantObject; + + const participant2 = { + type: "channel", + id: anotherChannel.resource.id, + company_id: anotherChannel.resource.company_id, + workspace_id: anotherChannel.resource.workspace_id, + } as ParticipantObject; + + const file = new MessageFile(); + file.metadata = { external_id: undefined, source: undefined, name: "test" }; + + const firstThreadId = await createThread("Filtered thread", [participant]); + await createReply(firstThreadId, "Filtered message 1-1"); + await createReply(firstThreadId, "Filtered message 1-2"); + await createReply(firstThreadId, "Filtered message 1-3"); + await createReply(firstThreadId, "Filtered message 1-4", { files: [file] }); + + const secondThreadId = await createThread("Filtered thread 2", [participant2], anotherUserId); + await createReply(secondThreadId, "Filtered message 2-1"); + await createReply(secondThreadId, "Filtered message 2-2"); + await createReply(secondThreadId, "Filtered message 2-3"); + await createReply(secondThreadId, "Filtered message 2-4"); + + const thirdThreadId = await createThread("Filtered thread 3", [participant]); + await createReply(thirdThreadId, "Filtered message 3-1"); + await createReply(thirdThreadId, "Filtered message 3-2", { userId: anotherUserId }); + await createReply(thirdThreadId, "Filtered message 3-3", { userId: anotherUserId }); + await createReply(thirdThreadId, "Filtered message 3-4", { + userId: anotherUserId, + files: [file], }); + //Wait for indexation to happen + await new Promise(r => setTimeout(r, 3000)); + + // no limit + const resources0 = await search("Filtered", { limit: 10000 }); + expect(resources0.length).toEqual(10); + + const resources = await search("Filtered", { limit: 9 }); + expect(resources.length).toEqual(9); + + // check for the empty result set + const resources2 = await search("Nothing", { limit: 10 }); + expect(resources2.length).toEqual(0); + + // check for the user + const resources3 = await search("Filtered", { sender: anotherUserId }); + expect(resources3.length).toEqual(3); + + // check for the files + const resources4 = await search("Filtered", { has_files: true }); + expect(resources4.length).toEqual(2); + + // check for the user and files + const resources5 = await search("Filtered", { sender: anotherUserId, has_files: true }); + expect(resources5.length).toEqual(1); + done(); }); }); - async function createChannel(): Promise { - const channel = channelUtils.getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + async function createChannel(userId = platform.currentUser.id): Promise { + const channel = channelUtils.getChannel(userId); + const creationResult = await gr.services.channels.channels.save( channel, {}, - channelUtils.getContext(), + channelUtils.getContext({ id: userId }), ); return creationResult.entity; } - async function createThread(text, participants: ParticipantObject[]) { - const response = await e2e_createThread(platform, participants, createMessage({ text: text })); + async function createThread(text, participants: ParticipantObject[], owner?: string) { + const response = await e2e_createThread( + platform, + participants, + createMessage({ text: text, user_id: owner }), + owner, + ); const result: ResourceUpdateResponse = deserialize( ResourceUpdateResponse, @@ -138,12 +219,29 @@ describe("The /messages API", () => { return result.resource.id; } - async function createReply(threadId, text) { - return e2e_createMessage(platform, threadId, createMessage({ text })); + async function createReply(threadId, text, options?: { userId?: string; files?: MessageFile[] }) { + const cr = options?.userId ? { currentUser: { id: options?.userId } } : undefined; + + const message = { text, ...(options?.files ? { files: options.files } : {}) }; + + return e2e_createMessage(platform, threadId, createMessage(message, cr as TestPlatform)); } - async function search(searchString: string, companyId?: string): Promise { + async function search( + searchString: string, + options?: { + company_id?: string; + workspace_id?: string; + channel_id?: string; + limit?: number; + sender?: string; + has_files?: boolean; + }, + ): Promise { const jwtToken = await platform.auth.getJWTToken(); + + const query: any = options || {}; + const response = await platform.app.inject({ method: "GET", // url: `${url}/companies/${platform.workspace.company_id}/woskpaces/`, @@ -152,8 +250,8 @@ describe("The /messages API", () => { authorization: `Bearer ${jwtToken}`, }, query: { + ...query, q: searchString, - ...(companyId ? { search_company_id: companyId } : {}), }, }); diff --git a/twake/backend/node/test/e2e/messages/messages.threads.spec.ts b/twake/backend/node/test/e2e/messages/messages.threads.spec.ts index c6337fc6f2..98d798a2bc 100644 --- a/twake/backend/node/test/e2e/messages/messages.threads.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.threads.spec.ts @@ -1,17 +1,12 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; -import { UserMessageBookmark } from "../../../src/services/messages/entities/user-message-bookmarks"; -import { - ResourceDeleteResponse, - ResourceListResponse, - ResourceUpdateResponse, -} from "../../../src/utils/types"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +import { ResourceUpdateResponse } from "../../../src/utils/types"; import { deserialize } from "class-transformer"; -import { MessageServiceAPI } from "../../../src/services/messages/api"; -import { v4 as uuidv4, v1 as uuidv1 } from "uuid"; +import { v1 as uuidv1, v4 as uuidv4 } from "uuid"; import { Thread } from "../../../src/services/messages/entities/threads"; import { createMessage, createParticipant, e2e_createThread } from "./utils"; +import gr from "../../../src/services/global-resolver"; describe("The Messages Threads feature", () => { const url = "/internal/services/messages/v1"; @@ -25,7 +20,7 @@ describe("The Messages Threads feature", () => { "applications", "search", "storage", - "pubsub", + "message-queue", "user", "search", "files", @@ -125,10 +120,8 @@ describe("The Messages Threads feature", () => { }); it("should update thread participants when add participant", async done => { - const service = platform.platform.getProvider("messages"); - //Create thread - const thread = await service.threads.save( + const thread = await gr.services.messages.threads.save( { id: undefined, participants: [ @@ -184,10 +177,8 @@ describe("The Messages Threads feature", () => { }); it("should update thread participants when remove participant", async done => { - const service = platform.platform.getProvider("messages"); - //Create thread - const thread = await service.threads.save( + const thread = await gr.services.messages.threads.save( { id: undefined, participants: [ diff --git a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts index a885149b5b..a407e0099d 100644 --- a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.realtime.spec.ts @@ -1,9 +1,10 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import io from "socket.io-client"; -import { TestPlatform, init } from "../setup"; -import { MessageServiceAPI } from "../../../src/services/messages/api"; -import { TwakePlatform } from "../../../src/core/platform/platform"; +import { init, TestPlatform } from "../setup"; +import gr from "../../../src/services/global-resolver"; describe("The Bookmarks Realtime feature", () => { const url = "/internal/services/messages/v1"; @@ -17,7 +18,7 @@ describe("The Bookmarks Realtime feature", () => { "database", "search", "storage", - "pubsub", + "message-queue", "files", "user", "websocket", @@ -47,8 +48,6 @@ describe("The Bookmarks Realtime feature", () => { describe("On bookmark creation", () => { it("should notify the client", async done => { - const service = platform.platform.getProvider("messages"); - const jwtToken = await platform.auth.getJWTToken(); const roomToken = "twake"; @@ -59,14 +58,13 @@ describe("The Bookmarks Realtime feature", () => { .on("authenticated", () => { socket.on("realtime:join:error", () => done(new Error("Should not occur"))); socket.on("realtime:join:success", async () => { - await service.userBookmarks.save( + await gr.services.messages.userBookmarks.save( { company_id: platform.workspace.company_id, user_id: platform.currentUser.id, name: "mybookmarksaved", id: undefined, }, - {}, getContext(platform), ); }); @@ -90,16 +88,13 @@ describe("The Bookmarks Realtime feature", () => { describe("On bookmark removal", () => { it("should notify the client", async done => { - const service = platform.platform.getProvider("messages"); - - const instance = await service.userBookmarks.save( + const instance = await gr.services.messages.userBookmarks.save( { company_id: platform.workspace.company_id, user_id: platform.currentUser.id, name: "mybookmark", id: undefined, }, - {}, getContext(platform), ); @@ -113,7 +108,7 @@ describe("The Bookmarks Realtime feature", () => { .on("authenticated", () => { socket.on("realtime:join:error", () => done(new Error("Should not occur"))); socket.on("realtime:join:success", async () => { - await service.userBookmarks.delete( + await gr.services.messages.userBookmarks.delete( { company_id: platform.workspace.company_id, user_id: platform.currentUser.id, diff --git a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts index 716ac078a8..68cb02404b 100644 --- a/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.user-bookmarks.spec.ts @@ -1,15 +1,11 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; import { UserMessageBookmark } from "../../../src/services/messages/entities/user-message-bookmarks"; -import { - ResourceDeleteResponse, - ResourceListResponse, - ResourceUpdateResponse, -} from "../../../src/utils/types"; +import { ResourceListResponse, ResourceUpdateResponse } from "../../../src/utils/types"; import { deserialize } from "class-transformer"; -import { MessageServiceAPI } from "../../../src/services/messages/api"; -import { v4 as uuidv4, v1 as uuidv1 } from "uuid"; +import { v4 as uuidv4 } from "uuid"; +import gr from "../../../src/services/global-resolver"; describe("The Messages User Bookmarks feature", () => { const url = "/internal/services/messages/v1"; @@ -24,7 +20,7 @@ describe("The Messages User Bookmarks feature", () => { "files", "storage", "applications", - "pubsub", + "message-queue", "user", "search", "websocket", @@ -45,8 +41,6 @@ describe("The Messages User Bookmarks feature", () => { describe("On user manage bookmmarks", () => { it("should create new bookmark", async done => { - const service = platform.platform.getProvider("messages"); - const jwtToken = await platform.auth.getJWTToken(); const response = await platform.app.inject({ method: "POST", @@ -72,27 +66,32 @@ describe("The Messages User Bookmarks feature", () => { name: "mybookmark", }); - const list = await service.userBookmarks.list({}, {}, getContext(platform)); + const context = getContext(platform); + + const list = await gr.services.messages.userBookmarks.list({ + user_id: context.user.id, + company_id: context.company.id, + }); expect(list.getEntities().length).toBe(1); done(); }); it("should prevent duplicated bookmark", async done => { - const service = platform.platform.getProvider("messages"); + // const uuid = uuidv4(); - const uuid = uuidv4(); + const context = getContext(platform); - await service.userBookmarks.save( + const data = await gr.services.messages.userBookmarks.save( { - id: uuid, company_id: platform.workspace.company_id, user_id: platform.currentUser.id, name: "mybookmark", + test: "123", }, - {}, - getContext(platform), + context, ); + const uuid = data.entity.id; const jwtToken = await platform.auth.getJWTToken(); const response = await platform.app.inject({ @@ -120,29 +119,33 @@ describe("The Messages User Bookmarks feature", () => { name: "mybookmark", }); - const list = await service.userBookmarks.list({}, {}, getContext(platform)); + const list = await gr.services.messages.userBookmarks.list({ + user_id: context.user.id, + company_id: context.company.id, + }); expect(list.getEntities().length).toBe(1); done(); }); it("should remove bookmark", async done => { - const service = platform.platform.getProvider("messages"); - const id = uuidv4(); + const context = getContext(platform); - await service.userBookmarks.save( + await gr.services.messages.userBookmarks.save( { id, company_id: platform.workspace.company_id, user_id: platform.currentUser.id, name: "mybookmark", }, - {}, - getContext(platform), + context, ); - let list = await service.userBookmarks.list({}, {}, getContext(platform)); + let list = await gr.services.messages.userBookmarks.list({ + user_id: context.user.id, + company_id: context.company.id, + }); expect(list.getEntities().length).toBe(1); const jwtToken = await platform.auth.getJWTToken(); @@ -156,26 +159,34 @@ describe("The Messages User Bookmarks feature", () => { expect(response.statusCode).toBe(200); - list = await service.userBookmarks.list({}, {}, getContext(platform)); + list = await gr.services.messages.userBookmarks.list({ + user_id: context.user.id, + company_id: context.company.id, + }); expect(list.getEntities().length).toBe(0); done(); }); it("should list bookmarks", async done => { - const service = platform.platform.getProvider("messages"); + const context = getContext(platform); - await service.userBookmarks.save( + await gr.services.messages.userBookmarks.save( { id: uuidv4(), company_id: platform.workspace.company_id, user_id: platform.currentUser.id, name: "mybookmark", }, - {}, - getContext(platform), + context, ); + const list = await gr.services.messages.userBookmarks.list({ + user_id: context.user.id, + company_id: context.company.id, + }); + expect(list.getEntities().length).toBe(1); + const jwtToken = await platform.auth.getJWTToken(); const response = await platform.app.inject({ method: "GET", diff --git a/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts b/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts index b7cff2f0ac..14b0029870 100644 --- a/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts +++ b/twake/backend/node/test/e2e/messages/messages.views.channel.spec.ts @@ -1,17 +1,17 @@ import "reflect-metadata"; -import { describe, expect, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; -import { UserMessageBookmark } from "../../../src/services/messages/entities/user-message-bookmarks"; -import { - ResourceDeleteResponse, - ResourceListResponse, - ResourceUpdateResponse, -} from "../../../src/utils/types"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +import { ResourceListResponse, ResourceUpdateResponse } from "../../../src/utils/types"; import { deserialize } from "class-transformer"; -import { MessageServiceAPI } from "../../../src/services/messages/api"; -import { v4 as uuidv4, v1 as uuidv1 } from "uuid"; +import { v4 as uuidv4 } from "uuid"; import { Thread } from "../../../src/services/messages/entities/threads"; -import { createMessage, createParticipant, e2e_createMessage, e2e_createThread } from "./utils"; +import { + createMessage, + createParticipant, + e2e_createChannel, + e2e_createMessage, + e2e_createThread, +} from "./utils"; import { MessageWithReplies } from "../../../src/services/messages/types"; describe("The Messages feature", () => { @@ -27,7 +27,7 @@ describe("The Messages feature", () => { "storage", "files", "applications", - "pubsub", + "message-queue", "user", "websocket", "messages", @@ -48,7 +48,7 @@ describe("The Messages feature", () => { describe("On user use messages in channel view", () => { it("should create a message and retrieve it in channel view", async () => { - const channelId = uuidv4(); + const channel = await e2e_createChannel(platform, [platform.currentUser.id]); const response = await e2e_createThread( platform, @@ -56,7 +56,9 @@ describe("The Messages feature", () => { createParticipant( { type: "channel", - id: channelId, + id: channel.resource.id, + workspace_id: channel.resource.workspace_id, + company_id: channel.resource.company_id, }, platform, ), @@ -79,7 +81,9 @@ describe("The Messages feature", () => { createParticipant( { type: "channel", - id: channelId, + id: channel.resource.id, + workspace_id: channel.resource.workspace_id, + company_id: channel.resource.company_id, }, platform, ), @@ -95,7 +99,9 @@ describe("The Messages feature", () => { createParticipant( { type: "channel", - id: channelId, + id: channel.resource.id, + workspace_id: channel.resource.workspace_id, + company_id: channel.resource.company_id, }, platform, ), @@ -106,7 +112,7 @@ describe("The Messages feature", () => { const jwtToken = await platform.auth.getJWTToken(); const listResponse = await platform.app.inject({ method: "GET", - url: `${url}/companies/${platform.workspace.company_id}/workspaces/${platform.workspace.workspace_id}/channels/${channelId}/feed?replies_per_thread=3`, + url: `${url}/companies/${channel.resource.company_id}/workspaces/${channel.resource.workspace_id}/channels/${channel.resource.id}/feed?replies_per_thread=3&include_users=1`, headers: { authorization: `Bearer ${jwtToken}`, }, @@ -117,6 +123,8 @@ describe("The Messages feature", () => { listResponse.body, ); + await new Promise(resolve => setTimeout(resolve, 5000)); + expect(listResponse.statusCode).toBe(200); expect(listResult.resources.length).toBe(3); diff --git a/twake/backend/node/test/e2e/messages/utils.ts b/twake/backend/node/test/e2e/messages/utils.ts index 44e52f85e0..6a5380ec91 100644 --- a/twake/backend/node/test/e2e/messages/utils.ts +++ b/twake/backend/node/test/e2e/messages/utils.ts @@ -1,18 +1,50 @@ +import { deserialize } from "class-transformer"; import { getInstance as getMessageInstance, Message, } from "../../../src/services/messages/entities/messages"; import { ParticipantObject } from "../../../src/services/messages/entities/threads"; +import { Channel, ResourceCreateResponse } from "../../../src/utils/types"; import { TestPlatform } from "../setup"; const url = "/internal/services/messages/v1"; +export const e2e_createChannel = async ( + platform: TestPlatform, + members: string[], + owner?: string, +) => { + const jwtToken = await platform.auth.getJWTToken({ sub: owner || platform.currentUser.id }); + const response = await platform.app.inject({ + method: "POST", + url: `/internal/services/channels/v1/companies/${platform.workspace.company_id}/workspaces/direct/channels`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + payload: { + options: { + members, + }, + resource: { + description: "A direct channel description", + visibility: "direct", + }, + }, + }); + const channelCreateResult: ResourceCreateResponse = deserialize( + ResourceCreateResponse, + response.body, + ); + return channelCreateResult; +}; + export const e2e_createThread = async ( platform: TestPlatform, participants: ParticipantObject[], message: Message, + owner?: string, ) => { - const jwtToken = await platform.auth.getJWTToken(); + const jwtToken = await platform.auth.getJWTToken({ sub: owner || platform.currentUser.id }); const res = await platform.app.inject({ method: "POST", url: `${url}/companies/${platform.workspace.company_id}/threads`, @@ -21,7 +53,7 @@ export const e2e_createThread = async ( }, payload: { resource: { - participants: participants, + participants: participants || [], }, options: { message: message, diff --git a/twake/backend/node/test/e2e/notifications/mention.spec.ts b/twake/backend/node/test/e2e/notifications/mention.spec.ts index c4ee95a75a..bc3ae7d896 100644 --- a/twake/backend/node/test/e2e/notifications/mention.spec.ts +++ b/twake/backend/node/test/e2e/notifications/mention.spec.ts @@ -1,30 +1,30 @@ -import { describe, expect, it, beforeAll, afterAll } from "@jest/globals"; +import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; import { v1 as uuidv1 } from "uuid"; -import { TestPlatform, init } from "../setup"; -import ChannelServiceAPI from "../../../src/services/channels/provider"; +import { init, TestPlatform } from "../setup"; import { Channel } from "../../../src/services/channels/entities/channel"; import { ChannelMemberNotificationLevel } from "../../../src/services/channels/types"; import { User } from "../../../src/utils/types"; import { + ChannelMemberUtils, ChannelUtils, get as getChannelUtils, getMemberUtils, - ChannelMemberUtils, } from "../channels/utils"; import { MessageNotification } from "../../../src/services/messages/types"; import { IncomingPubsubMessage, - PubsubServiceAPI, -} from "../../../src/core/platform/services/pubsub/api"; + MessageQueueServiceAPI, +} from "../../../src/core/platform/services/message-queue/api"; import { ChannelMember } from "../../../src/services/channels/entities"; import { MentionNotification } from "../../../src/services/notifications/types"; +import gr from "../../../src/services/global-resolver"; describe("The notification for user mentions", () => { let platform: TestPlatform; let channelUtils: ChannelUtils; let channelMemberUtils: ChannelMemberUtils; - let channelService: ChannelServiceAPI; - let pubsubService: PubsubServiceAPI; + let pubsubService: MessageQueueServiceAPI; + // eslint-disable-next-line @typescript-eslint/no-empty-function let pubsubHandler: (message: IncomingPubsubMessage) => void = _ => {}; beforeAll(async () => { @@ -34,7 +34,7 @@ describe("The notification for user mentions", () => { "database", "search", "storage", - "pubsub", + "message-queue", "user", "websocket", "channels", @@ -51,8 +51,7 @@ describe("The notification for user mentions", () => { }); channelUtils = getChannelUtils(platform); channelMemberUtils = getMemberUtils(platform); - channelService = platform.platform.getProvider("channels"); - pubsubService = platform.platform.getProvider("pubsub"); + pubsubService = platform.platform.getProvider("message-queue"); pubsubService.subscribe("notification:mentions", message => { pubsubHandler(message); }); @@ -65,7 +64,7 @@ describe("The notification for user mentions", () => { async function createChannel(): Promise { const channel = channelUtils.getChannel(platform.currentUser.id); - const creationResult = await channelService.channels.save( + const creationResult = await gr.services.channels.channels.save( channel, {}, channelUtils.getContext(), @@ -74,13 +73,18 @@ describe("The notification for user mentions", () => { return creationResult.entity; } - async function joinChannel(userId: string, channel: Channel): Promise { + async function joinChannel( + userId: string, + channel: Channel, + notificationLevel?: ChannelMemberNotificationLevel, + ): Promise { const user: User = { id: userId }; const member = channelMemberUtils.getMember(channel, user); - const memberCreationResult = await channelService.members.save( + if (notificationLevel) member.notification_level = notificationLevel; + + const memberCreationResult = await gr.services.channels.members.save( member, - {}, channelUtils.getChannelContext(channel, user), ); return memberCreationResult.entity; @@ -92,9 +96,8 @@ describe("The notification for user mentions", () => { level: ChannelMemberNotificationLevel, ): Promise { member.notification_level = level; - await channelService.members.save( + await gr.services.channels.members.save( member, - {}, channelUtils.getChannelContext(channel, { id: member.user_id }), ); @@ -107,22 +110,87 @@ describe("The notification for user mentions", () => { }); } - it("should mention all users when preferences are default ones", async done => { + it("should mention all users when preferences are MENTION", async done => { const threadId = uuidv1(); const messageId = uuidv1(); const unknownUser = uuidv1(); const channel = await createChannel(); + const member = await joinChannel( + platform.currentUser.id, + channel, + ChannelMemberNotificationLevel.MENTIONS, + ); + const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); + const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); + + pushMessage({ + channel_id: channel.id, + company_id: channel.company_id, + creation_date: Date.now(), + id: messageId, + sender: platform.currentUser.id, + thread_id: threadId, + workspace_id: channel.workspace_id, + mentions: { + users: [member.user_id, member2.user_id, unknownUser, member3.user_id], + }, + title: "test", + text: "should mention all users when preferences are MENTION ones", + }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users + expect(message.data.mentions.users).toContain(member2.user_id); + expect(message.data.mentions.users).toContain(member3.user_id); + expect(message.data.mentions.users).not.toContain(unknownUser); + + done(); + }); + + it("should mention all users when preferences are default ones (ALL)", async done => { + const messageId = uuidv1(); + const unknownUser = uuidv1(); + const channel = await createChannel(); + const member = await joinChannel(platform.currentUser.id, channel); + const member2 = await joinChannel(uuidv1(), channel); + const member3 = await joinChannel(uuidv1(), channel); + + await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services + + pushMessage({ + channel_id: channel.id, + company_id: channel.company_id, + creation_date: Date.now(), + id: messageId, + sender: platform.currentUser.id, + thread_id: messageId, //Only thread initial messages generate notifications + workspace_id: channel.workspace_id, + title: "test", + text: "should mention all users when preferences are default ones (ALL)", + }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users + expect(message.data.mentions.users).toContain(member2.user_id); + expect(message.data.mentions.users).toContain(member3.user_id); + expect(message.data.mentions.users).not.toContain(unknownUser); + + done(); + }); + + it("should not mention users with preferences ALL for replies of threads there are not member of", async done => { + const threadId = uuidv1(); + const messageId = uuidv1(); + const channel = await createChannel(); const member = await joinChannel(platform.currentUser.id, channel); const member2 = await joinChannel(uuidv1(), channel); const member3 = await joinChannel(uuidv1(), channel); - pubsubHandler = message => { - expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).toContain(member3.user_id); - expect(message.data.mentions.users).not.toContain(unknownUser); - done(); - }; + await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services pushMessage({ channel_id: channel.id, @@ -133,11 +201,19 @@ describe("The notification for user mentions", () => { thread_id: threadId, workspace_id: channel.workspace_id, mentions: { - users: [member.user_id, member2.user_id, unknownUser, member3.user_id], + users: [member.user_id, member2.user_id], }, - title: "", - text: "", + title: "test", + text: "should mention all users when preferences are default ones (ALL)", }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); //The sender is not in the notified users + expect(message.data.mentions.users).not.toContain(member3.user_id); + + done(); }); it("should not mention user when notification level is set to NONE", async done => { @@ -145,18 +221,15 @@ describe("The notification for user mentions", () => { const messageId = uuidv1(); const unknownUser = uuidv1(); const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); - - await updateNotificationLevel(channel, member2, ChannelMemberNotificationLevel.NONE); + const member = await joinChannel( + platform.currentUser.id, + channel, + ChannelMemberNotificationLevel.MENTIONS, + ); + const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); + const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); - pubsubHandler = message => { - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member3.user_id); - expect(message.data.mentions.users).not.toContain(member2.user_id); - done(); - }; + await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services pushMessage({ channel_id: channel.id, @@ -169,28 +242,33 @@ describe("The notification for user mentions", () => { mentions: { users: [member.user_id, member2.user_id, unknownUser, member3.user_id], }, - title: "", - text: "", + title: "test", + text: "should not mention user when notification level is set to NONE", }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); + expect(message.data.mentions.users).toContain(member3.user_id); + expect(message.data.mentions.users).not.toContain(member2.user_id); + + done(); }); it("should mention user when notification level is set to channel mention and notification is for @all", async done => { const threadId = uuidv1(); const messageId = uuidv1(); const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); - - await updateNotificationLevel(channel, member2, ChannelMemberNotificationLevel.MENTIONS); - await updateNotificationLevel(channel, member3, ChannelMemberNotificationLevel.ME); + const member = await joinChannel( + platform.currentUser.id, + channel, + ChannelMemberNotificationLevel.MENTIONS, + ); + const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); + const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.ME); - pubsubHandler = message => { - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - done(); - }; + await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services pushMessage({ channel_id: channel.id, @@ -204,9 +282,18 @@ describe("The notification for user mentions", () => { users: [], specials: ["all"], }, - title: "", - text: "", + title: "test", + text: "should mention user when notification level is set to channel mention and notification is for @all", }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); + expect(message.data.mentions.users).toContain(member2.user_id); + expect(message.data.mentions.users).not.toContain(member3.user_id); + + done(); }); it("should mention user when notification level is set to channel mention and notification is for @here", async done => { @@ -214,18 +301,10 @@ describe("The notification for user mentions", () => { const messageId = uuidv1(); const channel = await createChannel(); const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); - - await updateNotificationLevel(channel, member2, ChannelMemberNotificationLevel.MENTIONS); - await updateNotificationLevel(channel, member3, ChannelMemberNotificationLevel.ME); + const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.MENTIONS); + const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.ME); - pubsubHandler = message => { - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - done(); - }; + await new Promise(resolve => setTimeout(resolve, 500)); //Wait for the channel members to be created on all services pushMessage({ channel_id: channel.id, @@ -239,27 +318,41 @@ describe("The notification for user mentions", () => { users: [], specials: ["here"], }, - title: "", - text: "", + title: "test", + text: "should mention user when notification level is set to channel mention and notification is for @here", }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + + //Sender dont get notified + expect(message.data.mentions.users).not.toContain(member.user_id); + expect(message.data.mentions.users).toContain(member2.user_id); + expect(message.data.mentions.users).not.toContain(member3.user_id); + + done(); }); - it("should mention user when notification level is set to ME", async done => { + it("should mention user when notification level is set to ME and updated notification later", async done => { const threadId = uuidv1(); const messageId = uuidv1(); const channel = await createChannel(); - const member = await joinChannel(platform.currentUser.id, channel); - const member2 = await joinChannel(uuidv1(), channel); - const member3 = await joinChannel(uuidv1(), channel); + const member = await joinChannel( + platform.currentUser.id, + channel, + ChannelMemberNotificationLevel.NONE, + ); + const member2 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); + const member3 = await joinChannel(uuidv1(), channel, ChannelMemberNotificationLevel.NONE); + + await new Promise(resolve => setTimeout(resolve, 1000)); //Wait for the channel members to be created + await updateNotificationLevel(channel, member, ChannelMemberNotificationLevel.MENTIONS); await updateNotificationLevel(channel, member2, ChannelMemberNotificationLevel.ME); + await updateNotificationLevel(channel, member3, ChannelMemberNotificationLevel.MENTIONS); - pubsubHandler = message => { - expect(message.data.mentions.users).not.toContain(member.user_id); - expect(message.data.mentions.users).not.toContain(member3.user_id); - expect(message.data.mentions.users).toContain(member2.user_id); - done(); - }; + await new Promise(resolve => setTimeout(resolve, 1000)); //Wait for the channel members to be created pushMessage({ channel_id: channel.id, @@ -272,8 +365,17 @@ describe("The notification for user mentions", () => { mentions: { users: [member2.user_id], }, - title: "", - text: "", + title: "test", + text: "should mention user when notification level is set to ME and updated notification later", }); + + const message = await new Promise>( + resolve => (pubsubHandler = resolve), + ); + expect(message.data.mentions.users).not.toContain(member.user_id); + expect(message.data.mentions.users).not.toContain(member3.user_id); + expect(message.data.mentions.users).toContain(member2.user_id); + + done(); }); }); diff --git a/twake/backend/node/test/e2e/run-all.js b/twake/backend/node/test/e2e/run-all.js index 98b7a4161f..a3e94df92a 100644 --- a/twake/backend/node/test/e2e/run-all.js +++ b/twake/backend/node/test/e2e/run-all.js @@ -1,9 +1,28 @@ -/** This too will clean up the languages keys if they are not used anywhere in the code */ +/** + * To run all tests in local development mode: + * cd twake/; docker-compose -f docker-compose.dev.tests.mongo.yml run -e NODE_OPTIONS=--unhandled-rejections=warn -e SEARCH_DRIVER=mongodb -e DB_DRIVER=mongodb -e PUBSUB_TYPE=local node npm run test:e2e + * + * To run only specific tests: + * cd twake/; docker-compose -f docker-compose.dev.tests.mongo.yml run -e NODE_OPTIONS=--unhandled-rejections=warn -e SEARCH_DRIVER=mongodb -e DB_DRIVER=mongodb -e PUBSUB_TYPE=local node npm run test:e2e -- test/e2e/application/app-create-update.spec.ts test/e2e/application/application-events.spec.ts + */ const fs = require("fs"); const path = require("path"); const cp = require("child_process"); +let localDevTests = process.argv.slice(2); + +//If we are in the CI tests we will run all the tests +if (process.env.CI || localDevTests.length === 0) { + localDevTests = false; +} + +if (localDevTests) { + console.log("Only this tests will be run:", localDevTests); +} else { + console.log("Will run all the tests"); +} + function exec(command, args, debug = false) { return new Promise(done => { const cmd = cp.spawn(command, args, { @@ -49,18 +68,23 @@ srcFiles = srcFiles.filter(p => p.indexOf(".spec.ts") >= 0 || p.indexOf(".test.t let failed = 0; let passed = 0; - for (const path of srcFiles) { + let summary = ""; + + for (const path of localDevTests || srcFiles) { const testName = `test/e2e/${path.split("test/e2e/")[1]}`; - const args = `${testName} --forceExit --coverage --detectOpenHandles --runInBand --testTimeout=60000 --verbose=true`; + const args = `${testName} --forceExit --detectOpenHandles --runInBand --testTimeout=60000 --verbose=true`; + try { - const out = await exec("jest", args.split(" ")); + //Show logs in the console if we are doing local dev tests + const out = await exec("jest", args.split(" "), !!localDevTests); if (out.code !== 0) { - //To get all the logs - await exec("jest", args.split(" "), true); + //To get all the logs, we run it again console.log(`FAIL ${testName}`); - console.log(`-- Data\n ${out.data}`); - console.log(`-- Error\n ${out.error || "(no error)"}`); + console.log(out.data); + console.log(out.error); + if (!localDevTests) await exec("jest", args.split(" "), true); failed++; + summary += `FAIL ${testName}\n`; } else { passed++; console.log(`PASS ${testName}`); @@ -73,6 +97,7 @@ srcFiles = srcFiles.filter(p => p.indexOf(".spec.ts") >= 0 || p.indexOf(".test.t } console.log(`\nResults: ${passed} passed, ${failed} failed, total ${failed + passed}`); + console.log(summary); process.exit(failed > 0 ? 1 : 0); })(); diff --git a/twake/backend/node/test/e2e/setup/index.ts b/twake/backend/node/test/e2e/setup/index.ts index 07e420ce44..54026c356b 100644 --- a/twake/backend/node/test/e2e/setup/index.ts +++ b/twake/backend/node/test/e2e/setup/index.ts @@ -6,8 +6,11 @@ import WebServerAPI from "../../../src/core/platform/services/webserver/provider import { DatabaseServiceAPI } from "../../../src/core/platform/services/database/api"; import AuthServiceAPI from "../../../src/core/platform/services/auth/provider"; import { Workspace } from "../../../src/utils/types"; -import { PubsubServiceAPI } from "../../../src/core/platform/services/pubsub/api"; +import { MessageQueueServiceAPI } from "../../../src/core/platform/services/message-queue/api"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import config from "config"; +import globalResolver from "../../../src/services/global-resolver"; type TokenPayload = { sub: string; @@ -29,7 +32,7 @@ export interface TestPlatform { workspace: Workspace; app: FastifyInstance; database: DatabaseServiceAPI; - pubsub: PubsubServiceAPI; + messageQueue: MessageQueueServiceAPI; authService: AuthServiceAPI; auth: { getJWTToken(payload?: TokenPayload): Promise; @@ -43,26 +46,35 @@ export interface TestPlatformConfiguration { let testPlatform: TestPlatform = null; -export async function init(testConfig?: TestPlatformConfiguration): Promise { +export async function init( + testConfig?: TestPlatformConfiguration, + prePlatformStartCallback?: (fastify: FastifyInstance) => void, +): Promise { if (!testPlatform) { const configuration: TwakePlatformConfiguration = { services: config.get("services"), servicesPath: pathResolve(__dirname, "../../../src/services/"), }; const platform = new TwakePlatform(configuration); - await platform.init(); - await platform.start(); + await globalResolver.doInit(platform); const app = platform.getProvider("webserver").getServer(); + + if (prePlatformStartCallback) { + prePlatformStartCallback(app); + } + + await platform.start(); + const database = platform.getProvider("database"); - const pubsub = platform.getProvider("pubsub"); + const messageQueue = platform.getProvider("message-queue"); const auth = platform.getProvider("auth"); testPlatform = { platform, app, - pubsub, + messageQueue, database, workspace: { company_id: "", workspace_id: "" }, currentUser: { id: "" }, @@ -83,7 +95,7 @@ export async function init(testConfig?: TestPlatformConfiguration): Promise { if (testPlatform) { testPlatform.app.server.close(); - //await testPlatform.pubsub.stop(); + //await testPlatform.messageQueue.stop(); } } diff --git a/twake/backend/node/test/e2e/statistics.spec.ts b/twake/backend/node/test/e2e/statistics.spec.ts index 9ef6919e23..4d70b35f38 100644 --- a/twake/backend/node/test/e2e/statistics.spec.ts +++ b/twake/backend/node/test/e2e/statistics.spec.ts @@ -1,8 +1,7 @@ -import { beforeAll, beforeEach, afterAll, describe, expect, it } from "@jest/globals"; +import { afterAll, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "./setup"; import { v1 as uuidv1 } from "uuid"; -import ChannelServiceAPI from "../../src/services/channels/provider"; import { createMessage, createParticipant, @@ -13,13 +12,12 @@ import { Thread } from "../../src/services/messages/entities/threads"; import { deserialize } from "class-transformer"; import { WorkspaceExecutionContext } from "../../src/services/channels/types"; import { ChannelUtils, get as getChannelUtils } from "./channels/utils"; -import { StatisticsAPI } from "../../src/services/statistics/types"; import { ResourceUpdateResponse, User } from "../../src/utils/types"; +import gr from "../../src/services/global-resolver"; describe("Statistics implementation", () => { let platform: TestPlatform; // let database: DatabaseServiceAPI; - let statisticsAPI: StatisticsAPI; let channelUtils: ChannelUtils; beforeAll(async ends => { @@ -27,8 +25,7 @@ describe("Statistics implementation", () => { services: ["database", "statistics", "webserver", "auth"], }); - statisticsAPI = platform.platform.getProvider("statistics"); - expect(statisticsAPI).toBeTruthy(); + expect(gr.services.statistics).toBeTruthy(); ends(); channelUtils = getChannelUtils(platform); @@ -45,24 +42,28 @@ describe("Statistics implementation", () => { }); it("Check statistics counters", async done => { - console.log(await statisticsAPI.get(undefined, "counter-test")); + console.log(await gr.services.statistics.get(undefined, "counter-test")); - expect(await statisticsAPI.get(undefined, "counter-test")).toEqual(0); + expect(await gr.services.statistics.get(undefined, "counter-test")).toEqual(0); - await statisticsAPI.increase(platform.workspace.company_id, "counter-test"); - await statisticsAPI.increase(platform.workspace.company_id, "counter-test"); + await gr.services.statistics.increase(platform.workspace.company_id, "counter-test"); + await gr.services.statistics.increase(platform.workspace.company_id, "counter-test"); const secondCompanyId = uuidv1(); - await statisticsAPI.increase(secondCompanyId, "counter-test"); - await statisticsAPI.increase(secondCompanyId, "counter-test"); - await statisticsAPI.increase(platform.workspace.company_id, "counter-test2"); - - expect(await statisticsAPI.get(platform.workspace.company_id, "counter-test")).toEqual(2); - expect(await statisticsAPI.get(secondCompanyId, "counter-test")).toEqual(2); - expect(await statisticsAPI.get(undefined, "counter-test")).toEqual(4); - - expect(await statisticsAPI.get(platform.workspace.company_id, "counter-test2")).toEqual(1); - expect(await statisticsAPI.get(secondCompanyId, "counter-test2")).toEqual(0); - expect(await statisticsAPI.get(undefined, "counter-test2")).toEqual(1); + await gr.services.statistics.increase(secondCompanyId, "counter-test"); + await gr.services.statistics.increase(secondCompanyId, "counter-test"); + await gr.services.statistics.increase(platform.workspace.company_id, "counter-test2"); + + expect(await gr.services.statistics.get(platform.workspace.company_id, "counter-test")).toEqual( + 2, + ); + expect(await gr.services.statistics.get(secondCompanyId, "counter-test")).toEqual(2); + expect(await gr.services.statistics.get(undefined, "counter-test")).toEqual(4); + + expect( + await gr.services.statistics.get(platform.workspace.company_id, "counter-test2"), + ).toEqual(1); + expect(await gr.services.statistics.get(secondCompanyId, "counter-test2")).toEqual(0); + expect(await gr.services.statistics.get(undefined, "counter-test2")).toEqual(1); done(); }); @@ -80,14 +81,13 @@ describe("Statistics implementation", () => { describe("On user use messages in channel view", () => { it("should create a message and retrieve it in channel view", async () => { - const channelService = platform.platform.getProvider("channels"); const channel = channelUtils.getChannel(); - await channelService.channels.save(channel, {}, getContext()); + await gr.services.channels.channels.save(channel, {}, getContext()); const channelId = channel.id; //Reset global value because messages could have been created somewhere else - const value = await statisticsAPI.get(undefined, "messages"); - await statisticsAPI.increase(undefined, "messages", -value); + const value = await gr.services.statistics.get(undefined, "messages"); + await gr.services.statistics.increase(undefined, "messages", -value); const response = await e2e_createThread( platform, @@ -146,8 +146,10 @@ describe("Statistics implementation", () => { await new Promise(r => setTimeout(r, 5000)); - expect(await statisticsAPI.get(undefined, "messages")).toEqual(6); - expect(await statisticsAPI.get(platform.workspace.company_id, "messages")).toEqual(6); + expect(await gr.services.statistics.get(undefined, "messages")).toEqual(6); + expect(await gr.services.statistics.get(platform.workspace.company_id, "messages")).toEqual( + 6, + ); }); }); }); diff --git a/twake/backend/node/test/e2e/users/users.search.spec.ts b/twake/backend/node/test/e2e/users/users.search.spec.ts index 729651113e..b95d1320e0 100644 --- a/twake/backend/node/test/e2e/users/users.search.spec.ts +++ b/twake/backend/node/test/e2e/users/users.search.spec.ts @@ -12,7 +12,7 @@ describe("The /users API", () => { services: [ "database", "search", - "pubsub", + "message-queue", "websocket", "webserver", "user", @@ -84,7 +84,7 @@ describe("The /users API", () => { await new Promise(r => setTimeout(r, 5000)); let resources = await search("ha"); - expect(resources.length).toBe(1); + expect(resources.length).toBe(2); resources = await search("bob rabiot"); @@ -95,6 +95,18 @@ describe("The /users API", () => { resources = await search("alexis"); expect(resources[0].email).toBe("alexis.goelans@twake.app"); + resources = await search("ALEXIS"); + expect(resources[0].email).toBe("alexis.goelans@twake.app"); + + resources = await search("AleXis"); + expect(resources[0].email).toBe("alexis.goelans@twake.app"); + + resources = await search("alex"); + expect(resources[0].email).toBe("alexis.goelans@twake.app"); + + resources = await search("àlèXïs"); + expect(resources[0].email).toBe("alexis.goelans@twake.app"); + resources = await search("rbs"); expect(resources[0].email).toBe("rbs@twake.app"); diff --git a/twake/backend/node/test/e2e/users/users.spec.ts b/twake/backend/node/test/e2e/users/users.spec.ts index 92f849fb59..07104be5c2 100644 --- a/twake/backend/node/test/e2e/users/users.spec.ts +++ b/twake/backend/node/test/e2e/users/users.spec.ts @@ -1,7 +1,18 @@ -import { beforeAll, afterAll, afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; +import { CompanyLimitsEnum, UserObject } from "../../../src/services/user/web/types"; +import { Channel } from "../../../src/services/channels/entities"; +import { ChannelVisibility } from "../../../src/services/channels/types"; +import gr from "../../../src/services/global-resolver"; +import { ResourceListResponse, Workspace } from "../../../src/utils/types"; +import { ChannelSaveOptions } from "../../../src/services/channels/web/types"; +import { createMessage, e2e_createThread } from "../messages/utils"; +import { ChannelObject } from "../../../src/services/channels/services/channel/types"; +import { deserialize } from "class-transformer"; +import { ChannelUtils, get as getChannelUtils } from "../channels/utils"; +import { Api } from "../utils.api"; describe("The /users API", () => { const url = "/internal/services/users/v1"; @@ -26,7 +37,7 @@ describe("The /users API", () => { services: [ "database", "search", - "pubsub", + "message-queue", "websocket", "applications", "webserver", @@ -285,9 +296,8 @@ describe("The /users API", () => { expect(resource.plan).toMatchObject({ name: expect.any(String), limits: expect.objectContaining({ - members: expect.any(Number), - guests: expect.any(Number), - storage: expect.any(Number), + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]: expect.any(Number || undefined), + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]: expect.any(Number || undefined), }), }); } @@ -334,9 +344,8 @@ describe("The /users API", () => { expect(json.resource.plan).toMatchObject({ name: expect.any(String), limits: expect.objectContaining({ - members: expect.any(Number), - guests: expect.any(Number), - storage: expect.any(Number), + [CompanyLimitsEnum.CHAT_MESSAGE_HISTORY_LIMIT]: expect.any(Number || undefined), + [CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT]: expect.any(Number || undefined), }), }); } @@ -551,4 +560,89 @@ describe("The /users API", () => { }); }); }); + + describe("Recent contacts", () => { + it("should return list of recent contacts of user", async done => { + // api = new Api(platform); + const channelUtils = getChannelUtils(platform); + + await testDbService.createDefault(platform); + + const channels = []; + + for (let i = 0; i < 5; i++) { + // const channel = channelUtils.getChannel(); + const directChannelIn = channelUtils.getDirectChannel(); + + const nextUser = await testDbService.createUser( + [{ id: platform.workspace.workspace_id, company_id: platform.workspace.company_id }], + { firstName: "FirstName" + i, lastName: "LastName" + i }, + ); + + const members = [platform.currentUser.id, nextUser.id]; + const directWorkspace: Workspace = { + company_id: platform.workspace.company_id, + workspace_id: ChannelVisibility.DIRECT, + }; + await Promise.all([ + // gr.services.channels.channels.save(channel, {}, getContext()), + gr.services.channels.channels.save( + directChannelIn, + { + members, + }, + { + ...{ + workspace: platform.workspace, + user: platform.currentUser, + }, + ...{ workspace: directWorkspace }, + }, + ), + ]); + channels.push(directChannelIn); + } + + await new Promise(resolve => setTimeout(resolve, 1000)); + + await e2e_createThread( + platform, + [ + { + company_id: platform.workspace.company_id, + created_at: 0, + created_by: "", + id: channels[2].id, + type: "channel", + workspace_id: "direct", + }, + ], + createMessage({ text: "Some message" }), + ); + + await new Promise(resolve => setTimeout(resolve, 1000)); + + const jwtToken = await platform.auth.getJWTToken(); + + const response = await platform.app.inject({ + method: "GET", + url: `${url}/companies/${platform.workspace.company_id}/users/recent`, + headers: { + authorization: `Bearer ${jwtToken}`, + }, + }); + + expect(response.statusCode).toBe(200); + + const result: ResourceListResponse = deserialize( + ResourceListResponse, + response.body, + ); + + expect(result.resources.length).toEqual(5); + expect(result.resources[0].first_name).toEqual("FirstName2"); + + done(); + }); + }); }); diff --git a/twake/backend/node/test/e2e/utils.api.ts b/twake/backend/node/test/e2e/utils.api.ts index 626e61b6d3..b7ef87ab94 100644 --- a/twake/backend/node/test/e2e/utils.api.ts +++ b/twake/backend/node/test/e2e/utils.api.ts @@ -14,9 +14,11 @@ export class Api { private async convertResponse(response: Promise): Promise { const apiResponse = (await response) as ApiResponse; - const json = apiResponse.json(); - apiResponse.resources = json.resources; - apiResponse.resource = json.resource; + if (apiResponse.statusCode !== 204) { + const json = apiResponse.json(); + apiResponse.resources = json.resources; + apiResponse.resource = json.resource; + } return apiResponse; } @@ -29,29 +31,43 @@ export class Api { url: string, payload: InjectPayload, userId: string, + headers: any, ): Promise { if (!userId) userId = this.platform.currentUser.id; + let totalHeaders = { authorization: `Bearer ${await this.getJwtToken(userId)}` }; + + if (headers) { + totalHeaders = { ...totalHeaders, ...headers }; + } + return this.convertResponse( this.platform.app .inject({ method, url, - headers: { authorization: `Bearer ${await this.getJwtToken(userId)}` }, + headers: totalHeaders, payload, }) .then(a => { - log.debug(a.json(), `${method} ${url}`); + if (a.statusCode !== 204) { + log.debug(a.json(), `${method} ${url}`); + } return a; }), ); } - public async get(url: string, userId?: string): Promise { - return this.request("GET", url, undefined, userId); + public async get(url: string, userId?: string, headers?: any): Promise { + return this.request("GET", url, undefined, userId, headers); } - public async post(url: string, payload: InjectPayload, userId?: string): Promise { - return this.request("POST", url, payload, userId); + public async post( + url: string, + payload: InjectPayload, + userId?: string, + headers?: any, + ): Promise { + return this.request("POST", url, payload, userId, headers); } } diff --git a/twake/backend/node/test/e2e/utils.prepare.db.ts b/twake/backend/node/test/e2e/utils.prepare.db.ts index b971b74270..b8cdfa3c8a 100644 --- a/twake/backend/node/test/e2e/utils.prepare.db.ts +++ b/twake/backend/node/test/e2e/utils.prepare.db.ts @@ -1,5 +1,4 @@ import { TestPlatform } from "./setup"; -import UserServiceAPI from "./../../src/services/user/api"; import User from "./../../src/services/user/entities/user"; import Company, { getInstance as getCompanyInstance, @@ -14,14 +13,15 @@ import CompanyUser from "../../src/services/user/entities/company_user"; import { DatabaseServiceAPI } from "../../src/core/platform/services/database/api"; import Repository from "../../src/core/platform/services/database/services/orm/repository/repository"; import Device from "../../src/services/user/entities/device"; -import WorkspaceServicesAPI from "../../src/services/workspaces/api"; -import PlatformService from "../../src/core/platform/services/platform-services"; + +import gr from "../../src/services/global-resolver"; +import { Channel } from "../../src/services/channels/entities"; +import { get as getChannelUtils } from "./channels/utils"; export type uuid = string; export class TestDbService { private deviceRepository: Repository; - private workspaceService: WorkspaceServicesAPI; public static async getInstance( testPlatform: TestPlatform, @@ -47,12 +47,13 @@ export class TestDbService { private userRepository: Repository; constructor(protected testPlatform: TestPlatform) { - this.userService = this.testPlatform.platform.getProvider("user"); - this.workspaceService = - this.testPlatform.platform.getProvider("workspaces"); this.database = this.testPlatform.platform.getProvider("database"); this.users = []; this.workspacesMap = new Map(); + this.workspacesMap.set("direct", { + workspace: { id: "direct" } as Workspace, + users: [], + }); } private async init() { @@ -63,17 +64,18 @@ export class TestDbService { ); this.deviceRepository = await this.database.getRepository("device", Device); } + public get workspaces() { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - return [...this.workspacesMap.values()]; + return [...this.workspacesMap.values()].filter(w => w.workspace.id !== "direct"); } async createCompany(id?: uuid, name?: string): Promise { if (!name) { name = `TwakeAutotests-test-company-${this.rand()}`; } - this.company = await this.userService.companies.createCompany( + this.company = await gr.services.companies.createCompany( getCompanyInstance({ id: id || uuidv1(), name: name, @@ -90,7 +92,7 @@ export class TestDbService { ): Promise { if (!workspacePk.company_id) throw new Error("company_id is not defined for workspace"); - const workspace = await this.workspaceService.workspaces.create( + const workspace = await gr.services.workspaces.create( getWorkspaceInstance({ id: workspacePk.id, name: name, @@ -100,7 +102,7 @@ export class TestDbService { { user: { id: "", server_request: true } }, ); - const createdWorkspace = await this.workspaceService.workspaces.get({ + const createdWorkspace = await gr.services.workspaces.get({ id: workspacePk.id, company_id: workspacePk.company_id, }); @@ -149,14 +151,14 @@ export class TestDbService { if (options.email) { user.email_canonical = options.email; } - const createdUser = await this.userService.users.create(user).then(a => a.entity); + const createdUser = (await gr.services.users.create(user)).entity; if (options.password) { - await this.userService.users.setPassword({ id: createdUser.id }, options.password); + await gr.services.users.setPassword({ id: createdUser.id }, options.password); } this.users.push(createdUser); - await this.userService.companies.setUserRole( + await gr.services.companies.setUserRole( this.company ? this.company.id : workspacesPk[0].company_id, createdUser.id, options.companyRole ? options.companyRole : "member", @@ -164,7 +166,7 @@ export class TestDbService { if (workspacesPk && workspacesPk.length) { for (const workspacePk of workspacesPk) { - await this.workspaceService.workspaces.addUser( + await gr.services.workspaces.addUser( workspacePk, { id: createdUser.id }, options.workspaceRole ? options.workspaceRole : "member", @@ -179,9 +181,9 @@ export class TestDbService { async getUserFromDb(user: Partial>): Promise { if (user.id) { - return this.userService.users.get({ id: user.id }); + return gr.services.users.get({ id: user.id }); } else if (user.identity_provider_id) { - return this.userService.users.getByConsoleId(user.identity_provider_id); + return gr.services.users.getByConsoleId(user.identity_provider_id); } else { throw new Error("getUserFromDb: Id not provided"); } @@ -192,11 +194,11 @@ export class TestDbService { } getCompanyFromDb(companyId: uuid) { - return this.userService.companies.getCompany({ id: companyId }); + return gr.services.companies.getCompany({ id: companyId }); } getCompanyFromDbByCode(code: uuid) { - return this.userService.companies.getCompany({ identity_provider_id: code }); + return gr.services.companies.getCompany({ identity_provider_id: code }); } async getCompanyUsers(companyId: uuid): Promise { @@ -217,15 +219,15 @@ export class TestDbService { } getCompanyUser(companyId: uuid, userId: uuid): Promise { - return this.userService.companies.getCompanyUser({ id: companyId }, { id: userId }); + return gr.services.companies.getCompanyUser({ id: companyId }, { id: userId }); } getWorkspaceUsersCountFromDb(workspaceId: string) { - return this.workspaceService.workspaces.getUsersCount(workspaceId); + return gr.services.workspaces.getUsersCount(workspaceId); } async getCompanyUsersCountFromDb(companyId: string) { - return this.userService.companies.getUsersCount(companyId); + return gr.services.companies.getUsersCount(companyId); } async createDefault( @@ -257,4 +259,15 @@ export class TestDbService { defaultWorkspace() { return this.workspaces[0].workspace; } + + async createChannel(userId): Promise { + const channelUtils = getChannelUtils(this.testPlatform); + const channel = channelUtils.getChannel(userId); + const creationResult = await gr.services.channels.channels.save( + channel, + {}, + channelUtils.getContext({ id: userId }), + ); + return creationResult.entity; + } } diff --git a/twake/backend/node/test/e2e/websocket/auth.spec.ts b/twake/backend/node/test/e2e/websocket/auth.spec.ts index b59540ce8f..2326101c1b 100644 --- a/twake/backend/node/test/e2e/websocket/auth.spec.ts +++ b/twake/backend/node/test/e2e/websocket/auth.spec.ts @@ -1,7 +1,8 @@ -import { describe, it, beforeEach, afterEach } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; +import { afterEach, beforeEach, describe, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import io from "socket.io-client"; -import { UnauthorizedError } from "socketio-jwt"; describe("The Websocket authentication", () => { let platform: TestPlatform; @@ -14,7 +15,7 @@ describe("The Websocket authentication", () => { "database", "search", "storage", - "pubsub", + "message-queue", "user", "websocket", "webserver", @@ -50,8 +51,7 @@ describe("The Websocket authentication", () => { .on("authenticated", () => { done(new Error("Should not occur")); }) - .on("unauthorized", (msg: UnauthorizedError) => { - console.log(`unauthorized: ${JSON.stringify(msg.data)}`); + .on("unauthorized", (msg: any) => { done(); }); }); @@ -65,8 +65,7 @@ describe("The Websocket authentication", () => { .on("authenticated", () => { done(new Error("Should not occur")); }) - .on("unauthorized", (msg: UnauthorizedError) => { - console.log(`unauthorized: ${JSON.stringify(msg.data)}`); + .on("unauthorized", (msg: any) => { done(); }); }); diff --git a/twake/backend/node/test/e2e/websocket/realtime.spec.ts b/twake/backend/node/test/e2e/websocket/realtime.spec.ts index fb8bc77172..d519932852 100644 --- a/twake/backend/node/test/e2e/websocket/realtime.spec.ts +++ b/twake/backend/node/test/e2e/websocket/realtime.spec.ts @@ -1,5 +1,7 @@ -import { describe, it, beforeEach, afterEach, expect } from "@jest/globals"; -import { TestPlatform, init } from "../setup"; +import { afterEach, beforeEach, describe, expect, it } from "@jest/globals"; +import { init, TestPlatform } from "../setup"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import io from "socket.io-client"; describe("The Realtime API", () => { @@ -13,7 +15,7 @@ describe("The Realtime API", () => { "database", "search", "storage", - "pubsub", + "message-queue", "applications", "user", "auth", diff --git a/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts b/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts index f5760cf6d2..cc021fcbf7 100644 --- a/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts +++ b/twake/backend/node/test/e2e/workspaces/workspace-pending-users.spec.ts @@ -1,19 +1,15 @@ import { afterAll, beforeAll, describe, expect, it as _it } from "@jest/globals"; import { init, TestPlatform } from "../setup"; -import { TestDbService, uuid } from "../utils.prepare.db"; +import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; -import { ConsoleServiceAPI } from "../../../src/services/console/api"; -import { ConsoleType } from "../../../src/services/console/types"; - +import gr from "../../../src/services/global-resolver"; /* THIS TESTS RUNS ONLY FOR THE CONSOLE-MODE (CONSOLE TYPE: INTERNAL) */ -let consoleType: ConsoleType = null; - export const it = (name: string, cb: (a: any) => void) => { _it(name, async done => { - if (consoleType === "internal") { + if (gr.services.console.consoleType === "internal") { cb(done); } else { console.warn(`[skipped]: ${name} (no-console mode only)`); @@ -34,10 +30,11 @@ describe("The /workspace/pending users API", () => { const firstEmail = "first@test-user.com"; const secondEmail = "second@test-user.com"; const thirdEmail = "third@test-user.com"; + const fourthUser = "fourth@test-user.com"; const emailForExistedUser = "exist@email.com"; async function doTheTest() { - return Promise.resolve(consoleType === "remote"); + return Promise.resolve(gr.services.console.consoleType === "remote"); } beforeAll(async ends => { @@ -45,7 +42,7 @@ describe("The /workspace/pending users API", () => { services: [ "user", "database", - "pubsub", + "message-queue", "webserver", "search", "workspaces", @@ -65,8 +62,10 @@ describe("The /workspace/pending users API", () => { await testDbService.createCompany(companyId); const ws0pk = { id: uuidv1(), company_id: companyId }; const ws1pk = { id: uuidv1(), company_id: companyId }; + const ws2pk = { id: uuidv1(), company_id: companyId }; await testDbService.createWorkspace(ws0pk); await testDbService.createWorkspace(ws1pk); + await testDbService.createWorkspace(ws2pk); await testDbService.createUser([ws0pk], { companyRole: "member", workspaceRole: "moderator" }); await testDbService.createUser([ws0pk], { companyRole: "member", workspaceRole: "member" }); await testDbService.createUser([ws1pk], { @@ -74,9 +73,11 @@ describe("The /workspace/pending users API", () => { workspaceRole: "member", email: emailForExistedUser, }); - - const console = platform.platform.getProvider("console"); - consoleType = console.consoleType; + await testDbService.createUser([ws2pk], { + companyRole: "guest", + workspaceRole: "member", + email: fourthUser, + }); ends(); }); @@ -122,9 +123,9 @@ describe("The /workspace/pending users API", () => { done(); }); - it("should 403 when requester is not workspace moderator", async done => { - const workspace_id = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[1].id; + it("should 403 when requester is not at least workspace member", async done => { + const workspace_id = testDbService.workspaces[2].workspace.id; + const userId = testDbService.workspaces[2].users[0].id; const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -268,10 +269,10 @@ describe("The /workspace/pending users API", () => { done(); }); - it("should 403 when requester is not workspace moderator", async done => { + it("should 403 when requester is not at least workspace member", async done => { const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[1].id; + const workspaceId = testDbService.workspaces[2].workspace.id; + const userId = testDbService.workspaces[2].users[0].id; const email = "first@test-user.com"; const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -336,7 +337,7 @@ describe("The /workspace/pending users API", () => { const response = await platform.app.inject({ method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending/${email}`, + url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending`, }); expect(response.statusCode).toBe(401); done(); @@ -351,7 +352,7 @@ describe("The /workspace/pending users API", () => { const jwtToken = await platform.auth.getJWTToken({ sub: userId }); const response = await platform.app.inject({ method: "GET", - url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending/${email}`, + url: `${url}/companies/${companyId}/workspaces/${nonExistentId}/pending`, headers: { authorization: `Bearer ${jwtToken}` }, }); @@ -359,17 +360,17 @@ describe("The /workspace/pending users API", () => { done(); }); - it("should 403 when requester is not workspace moderator", async done => { + it("should 403 when requester is not at least workspace member", async done => { const companyId = testDbService.company.id; - const workspaceId = testDbService.workspaces[0].workspace.id; - const userId = testDbService.workspaces[0].users[1].id; + const workspaceId = testDbService.workspaces[2].workspace.id; + const userId = testDbService.workspaces[2].users[0].id; const email = "first@test-user.com"; const jwtToken = await platform.auth.getJWTToken({ sub: userId }); const response = await platform.app.inject({ method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending/${email}`, + url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending`, headers: { authorization: `Bearer ${jwtToken}` }, }); @@ -381,18 +382,18 @@ describe("The /workspace/pending users API", () => { const companyId = testDbService.company.id; const workspaceId = testDbService.workspaces[0].workspace.id; const userId = testDbService.workspaces[0].users[0].id; - const email = "first@test-user.com"; const jwtToken = await platform.auth.getJWTToken({ sub: userId }); const response = await platform.app.inject({ method: "GET", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending/${email}`, + url: `${url}/companies/${companyId}/workspaces/${workspaceId}/pending`, headers: { authorization: `Bearer ${jwtToken}` }, }); expect(response.statusCode).toBe(200); const resources = response.json()["resources"]; + console.log("resources A: ", resources); expect(resources.length).toBe(2); expect(resources[0]).toMatchObject({ @@ -427,6 +428,7 @@ describe("The /workspace/pending users API", () => { const resources = response.json()["resources"]; + console.log("resources B: ", resources); expect(resources.find((a: any) => a.user.email === emailForExistedUser)).toBeDefined(); done(); diff --git a/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts b/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts index c36a8e67c8..c70f2e836c 100644 --- a/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts +++ b/twake/backend/node/test/e2e/workspaces/workspace-users.spec.ts @@ -41,7 +41,7 @@ describe("The /workspace users API", () => { platform = await init({ services: [ "database", - "pubsub", + "message-queue", "search", "webserver", "user", @@ -73,6 +73,7 @@ describe("The /workspace users API", () => { await testDbService.createUser([ws2pk], { companyRole: "admin" }); await testDbService.createUser([ws2pk], { workspaceRole: "moderator" }); await testDbService.createUser([ws2pk], { workspaceRole: "member" }); + await testDbService.createUser([ws2pk], { workspaceRole: "member" }); await testDbService.createUser([], { companyRole: "member" }); await testDbService.createUser([ws3pk], { companyRole: "guest", workspaceRole: "member" }); ends(); @@ -264,7 +265,11 @@ describe("The /workspace users API", () => { let workspaceUsersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); let companyUsersCount = await testDbService.getCompanyUsersCountFromDb(companyId); - expect(workspaceUsersCount).toBe(3); + + console.log(testDbService.workspaces[2].users); + console.log(workspaceUsersCount); + + expect(workspaceUsersCount).toBe(4); // expect(companyUsersCount).toBe(6); const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -286,7 +291,7 @@ describe("The /workspace users API", () => { workspaceUsersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); companyUsersCount = await testDbService.getCompanyUsersCountFromDb(companyId); - expect(workspaceUsersCount).toBe(4); + expect(workspaceUsersCount).toBe(5); // expect(companyUsersCount).toBe(6); done(); @@ -374,7 +379,7 @@ describe("The /workspace users API", () => { expect(resource["role"]).toBe("moderator"); const usersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - expect(usersCount).toBe(4); + expect(usersCount).toBe(5); done(); }); @@ -394,9 +399,10 @@ describe("The /workspace users API", () => { }); it("should 403 user is not workspace moderator", async done => { - const userId = testDbService.users[0].id; - const anotherUserId = testDbService.users[1].id; - const workspaceId = testDbService.workspaces[0].workspace.id; + const companyId = testDbService.company.id; + const workspaceId = testDbService.workspaces[2].workspace.id; + const userId = testDbService.workspaces[2].users[3].id; + const anotherUserId = testDbService.workspaces[2].users[1].id; const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -405,6 +411,9 @@ describe("The /workspace users API", () => { url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/${anotherUserId}`, headers: { authorization: `Bearer ${jwtToken}` }, }); + + console.log(response.body); + expect(response.statusCode).toBe(403); done(); }); @@ -452,7 +461,7 @@ describe("The /workspace users API", () => { expect(resources.find((a: { user_id: uuid }) => a.user_id === anotherUserId)).toBeUndefined(); const usersCount = await testDbService.getWorkspaceUsersCountFromDb(workspaceId); - expect(usersCount).toBe(3); + expect(usersCount).toBe(4); done(); }); diff --git a/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts b/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts index 1dd1f3ccdc..3f3f25e81a 100644 --- a/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts +++ b/twake/backend/node/test/e2e/workspaces/workspaces.invite-tokens.spec.ts @@ -2,17 +2,16 @@ import { afterAll, beforeAll, describe, expect, it } from "@jest/globals"; import { init, TestPlatform } from "../setup"; import { TestDbService } from "../utils.prepare.db"; import { v1 as uuidv1 } from "uuid"; -import WorkspaceServicesAPI from "../../../src/services/workspaces/api"; -import AuthServiceAPI from "../../../src/core/platform/services/auth/provider"; +import AuthService from "../../../src/core/platform/services/auth/provider"; import { InviteTokenObject } from "../../../src/services/workspaces/web/types"; +import gr from "../../../src/services/global-resolver"; describe("The /workspaces API (invite tokens)", () => { const url = "/internal/services/workspaces/v1"; let platform: TestPlatform; let testDbService: TestDbService; - let workspaceServicesAPI: WorkspaceServicesAPI; - let authServiceApi: AuthServiceAPI; + let authServiceApi: AuthService; let companyId = uuidv1(); @@ -20,7 +19,7 @@ describe("The /workspaces API (invite tokens)", () => { platform = await init({ services: [ "database", - "pubsub", + "message-queue", "webserver", "user", "search", @@ -37,8 +36,7 @@ describe("The /workspaces API (invite tokens)", () => { companyId = platform.workspace.company_id; - workspaceServicesAPI = await platform.platform.getProvider("workspaces"); - authServiceApi = await platform.platform.getProvider("auth"); + authServiceApi = await platform.platform.getProvider("auth"); testDbService = new TestDbService(platform); await resetDatabase(); }; @@ -64,7 +62,7 @@ describe("The /workspaces API (invite tokens)", () => { }; const decodeToken = (token: string): InviteTokenObject => { - return authServiceApi.verifyTokenObject(token); + return gr.services.workspaces.decodeInviteToken(token); }; describe("The GET /tokens/ route", () => { @@ -123,7 +121,7 @@ describe("The /workspaces API (invite tokens)", () => { const userId = testDbService.workspaces[0].users[0].id; const companyId = testDbService.company.id; - await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId); + await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -311,7 +309,7 @@ describe("The /workspaces API (invite tokens)", () => { const response = await platform.app.inject({ method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/123`, + url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake1-${new Date().getTime()}`, }); expect(response.statusCode).toBe(401); done(); @@ -326,7 +324,7 @@ describe("The /workspaces API (invite tokens)", () => { const response = await platform.app.inject({ method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/123`, + url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake2-${new Date().getTime()}`, headers: { authorization: `Bearer ${jwtToken}` }, payload: {}, }); @@ -340,7 +338,7 @@ describe("The /workspaces API (invite tokens)", () => { const userId = testDbService.workspaces[0].users[0].id; const companyId = testDbService.company.id; - await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId); + await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -382,7 +380,7 @@ describe("The /workspaces API (invite tokens)", () => { const response = await platform.app.inject({ method: "DELETE", - url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/123456`, + url: `${url}/companies/${companyId}/workspaces/${workspaceId}/users/tokens/fake3-${new Date().getTime()}`, headers: { authorization: `Bearer ${jwtToken}` }, payload: {}, }); @@ -403,7 +401,7 @@ describe("The /workspaces API (invite tokens)", () => { companyId = testDbService.company.id; workspaceId = testDbService.workspaces[0].workspace.id; userId = testDbService.workspaces[2].users[0].id; - inviteToken = await workspaceServicesAPI.workspaces.createInviteToken(companyId, workspaceId); + inviteToken = await gr.services.workspaces.createInviteToken(companyId, workspaceId, userId); }); afterAll(shutdown); @@ -424,8 +422,6 @@ describe("The /workspaces API (invite tokens)", () => { }); it("should 200 when user is not authorized", async done => { - const jwtToken = await platform.auth.getJWTToken({ sub: userId }); - const response = await platform.app.inject({ method: "POST", url: `${url}/join`, diff --git a/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts b/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts index cbcf625726..d251e3040f 100644 --- a/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts +++ b/twake/backend/node/test/e2e/workspaces/workspaces.spec.ts @@ -16,7 +16,7 @@ describe("The /workspaces API", () => { platform = await init({ services: [ "database", - "pubsub", + "message-queue", "webserver", "user", "search", @@ -380,7 +380,7 @@ describe("The /workspaces API", () => { it("should 200 when admin of company (full update)", async done => { const companyId = testDbService.company.id; const workspaceId = testDbService.workspaces[2].workspace.id; - const userId = testDbService.workspaces[2].users[0].id; // company moderator + const userId = testDbService.workspaces[2].users[0].id; // company owner const jwtToken = await platform.auth.getJWTToken({ sub: userId }); @@ -390,7 +390,7 @@ describe("The /workspaces API", () => { headers: { authorization: `Bearer ${jwtToken}` }, payload: { resource: { - name: "Another channel name", + name: "Another workspace name", logo: "logo", default: false, archived: false, @@ -405,11 +405,11 @@ describe("The /workspaces API", () => { expect(resource).toMatchObject({ id: workspaceId, company_id: companyId, - name: "Another channel name", + name: "Another workspace name", logo: expect.any(String), default: false, archived: false, - role: "member", + role: "moderator", //Company admin is a moderator }); done(); diff --git a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/created.test.ts b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/created.test.ts index e33d5fd688..19cd9250a2 100644 --- a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/created.test.ts +++ b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/created.test.ts @@ -1,15 +1,17 @@ import { describe, expect, it, jest } from "@jest/globals"; import { CreateResult } from "../../../../../../../src/core/platform/framework/api/crud-service"; import { RealtimeCreated } from "../../../../../../../src/core/platform/framework/decorators"; -import { eventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; +import { websocketEventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; import { ResourcePath } from "../../../../../../../src/core/platform/services/realtime/types"; describe("The RealtimeCreated decorator", () => { it("should call the original method send back original result but do not emit event if result type is wrong", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeCreated({ room: "/foo/bar" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore reverseMeBaby(input: string): Promise { return Promise.resolve(input.split("").reverse().join("")); } @@ -29,10 +31,12 @@ describe("The RealtimeCreated decorator", () => { }); it("should call the original method send back original result and emit event", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeCreated({ room: "/foo/bar", path: "/foo/bar/baz" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new CreateResult("string", input.split("").reverse().join("")); } @@ -68,12 +72,14 @@ describe("The RealtimeCreated decorator", () => { }); it("should emit event with path computed from function", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeCreated(input => [ { room: ResourcePath.get(`/foo/bar/${input}`), path: "/foo/bar/baz" }, ]) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new CreateResult("string", input.split("").reverse().join("")); } diff --git a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/deleted.test.ts b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/deleted.test.ts index a500f3dbc1..d41290bad2 100644 --- a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/deleted.test.ts +++ b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/deleted.test.ts @@ -1,15 +1,17 @@ import { describe, expect, it, jest } from "@jest/globals"; import { DeleteResult } from "../../../../../../../src/core/platform/framework/api/crud-service"; import { RealtimeDeleted } from "../../../../../../../src/core/platform/framework/decorators"; -import { eventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; +import { websocketEventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; import { ResourcePath } from "../../../../../../../src/core/platform/services/realtime/types"; describe("The RealtimeDeleted decorator", () => { it("should call the original method send back original result but do not emit event if result type is wrong", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeDeleted({ room: "/foo/bar" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore reverseMeBaby(input: string): Promise { return Promise.resolve(input.split("").reverse().join("")); } @@ -29,10 +31,12 @@ describe("The RealtimeDeleted decorator", () => { }); it("should call the original method send back original result and emit event", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeDeleted({ room: "/foo/bar", path: "/foo/bar/baz" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new DeleteResult("string", input.split("").reverse().join(""), true); } @@ -68,12 +72,14 @@ describe("The RealtimeDeleted decorator", () => { }); it("should emit event with path computed from function", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeDeleted(result => [ { room: ResourcePath.get(`/foo/bar/${result}`), path: "/foo/bar/baz" }, ]) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new DeleteResult("string", input.split("").reverse().join(""), true); } diff --git a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/updated.test.ts b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/updated.test.ts index 071e1b26aa..af2929cbfb 100644 --- a/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/updated.test.ts +++ b/twake/backend/node/test/unit/core/platform/framework/decorators/realtime/updated.test.ts @@ -1,15 +1,17 @@ import { describe, expect, it, jest } from "@jest/globals"; import { UpdateResult } from "../../../../../../../src/core/platform/framework/api/crud-service"; import { RealtimeUpdated } from "../../../../../../../src/core/platform/framework/decorators"; -import { eventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; +import { websocketEventBus } from "../../../../../../../src/core/platform/services/realtime/bus"; import { ResourcePath } from "../../../../../../../src/core/platform/services/realtime/types"; describe("The RealtimeUpdated decorator", () => { it("should call the original method send back original result but do not emit event if result type is wrong", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeUpdated({ room: "/foo/bar" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore reverseMeBaby(input: string): Promise { return Promise.resolve(input.split("").reverse().join("")); } @@ -29,10 +31,12 @@ describe("The RealtimeUpdated decorator", () => { }); it("should call the original method send back original result and emit event", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeUpdated({ room: "/foo/bar", path: "/foo/bar/baz" }) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new UpdateResult("string", input.split("").reverse().join("")); } @@ -69,12 +73,14 @@ describe("The RealtimeUpdated decorator", () => { }); it("should emit event with path computed from function", async done => { - const emitSpy = jest.spyOn(eventBus, "emit"); + const emitSpy = jest.spyOn(websocketEventBus, "emit"); class TestMe { @RealtimeUpdated(result => [ { room: ResourcePath.get(`/foo/bar/${result}`), path: "/foo/bar/baz" }, ]) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore async reverseMeBaby(input: string): Promise> { return new UpdateResult("string", input.split("").reverse().join("")); } diff --git a/twake/backend/node/test/unit/core/services/database/services/utils.test.ts b/twake/backend/node/test/unit/core/services/database/services/utils.test.ts index 84efa54e55..11fbac06c2 100644 --- a/twake/backend/node/test/unit/core/services/database/services/utils.test.ts +++ b/twake/backend/node/test/unit/core/services/database/services/utils.test.ts @@ -4,6 +4,8 @@ import { fromMongoDbOrderable, toMongoDbOrderable, } from "../../../../../../src/core/platform/services/database/services/orm/utils"; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore import _ from "lodash"; import { v1 as uuidv1 } from "uuid"; diff --git a/twake/backend/node/test/unit/core/services/pubsub/processor/pubsubserviceprocessor.test.ts b/twake/backend/node/test/unit/core/services/pubsub/processor/pubsubserviceprocessor.test.ts index b4901ea61a..854f301e8a 100644 --- a/twake/backend/node/test/unit/core/services/pubsub/processor/pubsubserviceprocessor.test.ts +++ b/twake/backend/node/test/unit/core/services/pubsub/processor/pubsubserviceprocessor.test.ts @@ -1,13 +1,13 @@ import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals"; import { - IncomingPubsubMessage, - PubsubHandler, - PubsubServiceAPI, - PubsubServiceProcessor, -} from "../../../../../../src/core/platform/services/pubsub/api"; - -describe("The PubsubServiceProcessor class", () => { - let pubsubService: PubsubServiceAPI; + IncomingMessageQueueMessage, + MessageQueueHandler, + MessageQueueServiceAPI, + MessageQueueServiceProcessor, +} from "../../../../../../src/core/platform/services/message-queue/api"; + +describe("The MessageQueueServiceProcessor class", () => { + let pubsubService: MessageQueueServiceAPI; let subscribe; let publish; let topic; @@ -20,10 +20,10 @@ describe("The PubsubServiceProcessor class", () => { outTopic = "outTopic"; subscribe = jest.fn(); publish = jest.fn(); - pubsubService = ({ + pubsubService = { publish, subscribe, - } as unknown) as PubsubServiceAPI; + } as unknown as MessageQueueServiceAPI; }); afterEach(() => { @@ -34,8 +34,8 @@ describe("The PubsubServiceProcessor class", () => { describe("The init function", () => { it("should not subscribe when topics is not defined", async () => { subscribe.mockResolvedValue(true); - const processor = new PubsubServiceProcessor( - {} as PubsubHandler, + const processor = new MessageQueueServiceProcessor( + {} as MessageQueueHandler, pubsubService, ); @@ -45,10 +45,10 @@ describe("The PubsubServiceProcessor class", () => { it("should not subscribe when topics.in is not defined", async () => { subscribe.mockResolvedValue(true); - const processor = new PubsubServiceProcessor( + const processor = new MessageQueueServiceProcessor( { topics: {}, - } as PubsubHandler, + } as MessageQueueHandler, pubsubService, ); @@ -58,12 +58,12 @@ describe("The PubsubServiceProcessor class", () => { it("should subscribe when topics.in is defined", async () => { subscribe.mockResolvedValue(true); - const processor = new PubsubServiceProcessor( + const processor = new MessageQueueServiceProcessor( { topics: { in: topic, }, - } as PubsubHandler, + } as MessageQueueHandler, pubsubService, ); @@ -78,17 +78,17 @@ describe("The PubsubServiceProcessor class", () => { it("should not process data when data is not valid", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; const validate = jest.fn().mockReturnValue(false); const process = jest.fn().mockReturnValue(true); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, }, validate, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -104,17 +104,17 @@ describe("The PubsubServiceProcessor class", () => { it("should process data when data is valid", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; const validate = jest.fn().mockReturnValue(true); const process = jest.fn().mockReturnValue(true); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, }, validate, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -132,15 +132,15 @@ describe("The PubsubServiceProcessor class", () => { it("should not publish error when topics.error is not defined", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; const process = jest.fn().mockRejectedValue(new Error("I failed to process")); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -156,16 +156,16 @@ describe("The PubsubServiceProcessor class", () => { it("should publish error when topics.error is defined", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; const process = jest.fn().mockRejectedValue(new Error("I failed to process")); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, error: errorTopic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -182,17 +182,19 @@ describe("The PubsubServiceProcessor class", () => { it("should not publish when processing does not return result", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const process = jest.fn().mockResolvedValue(null); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, out: outTopic, error: errorTopic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -208,16 +210,18 @@ describe("The PubsubServiceProcessor class", () => { it("should not publish when out topic is not defined", async () => { const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const process = jest.fn().mockResolvedValue(true); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, error: errorTopic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -234,17 +238,19 @@ describe("The PubsubServiceProcessor class", () => { const result = "processing result"; const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const process = jest.fn().mockResolvedValue(result); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, error: errorTopic, out: outTopic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); @@ -268,17 +274,19 @@ describe("The PubsubServiceProcessor class", () => { const result = "processing result"; const message = { data: "foo", - } as IncomingPubsubMessage; + } as IncomingMessageQueueMessage; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore const process = jest.fn().mockResolvedValue(result); - const processor = new PubsubServiceProcessor( - ({ + const processor = new MessageQueueServiceProcessor( + { topics: { in: topic, error: errorTopic, out: outTopic, }, process, - } as unknown) as PubsubHandler, + } as unknown as MessageQueueHandler, pubsubService, ); diff --git a/twake/backend/node/test/unit/services/notifications/services/engine/processors/new-channel-message/index.test.ts b/twake/backend/node/test/unit/services/notifications/services/engine/processors/new-channel-message/index.test.ts index ee9659a521..4688d43182 100644 --- a/twake/backend/node/test/unit/services/notifications/services/engine/processors/new-channel-message/index.test.ts +++ b/twake/backend/node/test/unit/services/notifications/services/engine/processors/new-channel-message/index.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { ListResult, OperationType, @@ -6,17 +6,17 @@ import { } from "../../../../../../../../src/core/platform/framework/api/crud-service"; import { ChannelMemberNotificationLevel } from "../../../../../../../../src/services/channels/types"; import { MessageNotification } from "../../../../../../../../src/services/messages/types"; -import { NotificationServiceAPI } from "../../../../../../../../src/services/notifications/api"; import { ChannelMemberNotificationPreference, ChannelThreadUsers, } from "../../../../../../../../src/services/notifications/entities"; -import { NewChannelMessageProcessor } from "../../../../../../../../src/services/notifications/services/engine/processors/new-channel-message/index"; import { ChannelType } from "../../../../../../../../src/utils/types"; +import gr from "../../../../../../../../src/services/global-resolver"; +import { NewChannelMessageProcessor } from "../../../../../../../../src/services/notifications/services/engine/processors/new-channel-message"; describe("The NewChannelMessageProcessor class", () => { let channel_id, company_id, workspace_id, thread_id; - let service: NotificationServiceAPI; + let service: any; let processor: NewChannelMessageProcessor; let getUsersInThread; let getChannelPreferencesForUsers; @@ -32,7 +32,7 @@ describe("The NewChannelMessageProcessor class", () => { setPreferences(); setUsersInThread(); - service = ({ + service = { channelThreads: { bulkSave: jest .fn() @@ -44,9 +44,13 @@ describe("The NewChannelMessageProcessor class", () => { channelPreferences: { getChannelPreferencesForUsers, }, - } as unknown) as NotificationServiceAPI; + }; - processor = new NewChannelMessageProcessor(service); + gr.services = { + notifications: service, + } as any; + + processor = new NewChannelMessageProcessor(); }); afterEach(() => { @@ -139,14 +143,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -165,14 +172,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -192,14 +202,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -219,14 +232,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -246,38 +262,41 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "1", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "2", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "3", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "4", - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "1", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "2", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "3", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "4", + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -298,38 +317,41 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: message.sender, - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "1", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "2", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "3", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.id, - user_id: "4", - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: message.sender, + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "1", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "2", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "3", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.id, + user_id: "4", + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).not.toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -383,14 +405,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -406,14 +431,17 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: message.sender, - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: message.sender, + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); @@ -430,38 +458,41 @@ describe("The NewChannelMessageProcessor class", () => { const result = await processor.process(message); expect(service.channelThreads.bulkSave).toBeCalledTimes(1); - expect(service.channelThreads.bulkSave).toBeCalledWith([ - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: message.sender, - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: "1", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: "2", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: "3", - }, - { - company_id: message.company_id, - channel_id: message.channel_id, - thread_id: message.thread_id, - user_id: "4", - }, - ]); + expect(service.channelThreads.bulkSave).toBeCalledWith( + [ + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: message.sender, + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: "1", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: "2", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: "3", + }, + { + company_id: message.company_id, + channel_id: message.channel_id, + thread_id: message.thread_id, + user_id: "4", + }, + ], + undefined, + ); expect(service.channelThreads.getUsersInThread).toBeCalled; expect(service.channelPreferences.getChannelPreferencesForUsers).toBeCalledTimes(1); diff --git a/twake/backend/node/test/unit/services/notifications/services/engine/processors/push-to-users/index.test.ts b/twake/backend/node/test/unit/services/notifications/services/engine/processors/push-to-users/index.test.ts index 38029c3726..11207143c1 100644 --- a/twake/backend/node/test/unit/services/notifications/services/engine/processors/push-to-users/index.test.ts +++ b/twake/backend/node/test/unit/services/notifications/services/engine/processors/push-to-users/index.test.ts @@ -1,33 +1,34 @@ import "reflect-metadata"; -import { describe, expect, it, jest, beforeEach, afterEach } from "@jest/globals"; +import { afterEach, beforeEach, describe, expect, it, jest } from "@jest/globals"; import { ListResult, OperationType, SaveResult, } from "../../../../../../../../src/core/platform/framework/api/crud-service"; -import { PubsubServiceAPI } from "../../../../../../../../src/core/platform/services/pubsub/api"; +import { MessageQueueServiceAPI } from "../../../../../../../../src/core/platform/services/message-queue/api"; import { ChannelMemberNotificationLevel } from "../../../../../../../../src/services/channels/types"; -import { NotificationServiceAPI } from "../../../../../../../../src/services/notifications/api"; -import { ChannelMemberNotificationPreference } from "../../../../../../../../src/services/notifications/entities/channel-member-notification-preferences"; -import { ChannelThreadUsers } from "../../../../../../../../src/services/notifications/entities/channel-thread-users"; import { - UserNotificationBadge, + ChannelMemberNotificationPreference, + ChannelThreadUsers, +} from "../../../../../../../../src/services/notifications/entities"; +import { TYPE as UserNotificationBadgeType, + UserNotificationBadge, } from "../../../../../../../../src/services/notifications/entities/user-notification-badges"; -import { PushNotificationToUsersMessageProcessor } from "../../../../../../../../src/services/notifications/services/engine/processors/push-to-users/index"; import { MentionNotification } from "../../../../../../../../src/services/notifications/types"; import { uniqueId } from "lodash"; +import { PushNotificationToUsersMessageProcessor } from "../../../../../../../../src/services/notifications/services/engine/processors/push-to-users"; +import gr from "../../../../../../../../src/services/global-resolver"; describe("The PushNotificationToUsersMessageProcessor class", () => { let channel_id, company_id, workspace_id, thread_id; - let service: NotificationServiceAPI; - let pubsubService: PubsubServiceAPI; + let pubsubService: MessageQueueServiceAPI; let processor: PushNotificationToUsersMessageProcessor; let getUsersInThread; let getChannelPreferencesForUsers; let saveBadge; - beforeEach(() => { + beforeEach(async () => { channel_id = "channel_id"; company_id = "company_id"; workspace_id = "workspace_id"; @@ -40,20 +41,27 @@ describe("The PushNotificationToUsersMessageProcessor class", () => { setPreferences(); setUsersInThread(); - pubsubService = ({ + pubsubService = { publish: jest.fn(), - } as unknown) as PubsubServiceAPI; - - service = ({ + } as unknown as MessageQueueServiceAPI; + // + const service = { badges: { save: saveBadge, }, channelPreferences: { getChannelPreferencesForUsers, }, - } as unknown) as NotificationServiceAPI; + }; + + gr.platformServices = { + messageQueue: pubsubService, + } as any; - processor = new PushNotificationToUsersMessageProcessor(service, pubsubService); + gr.services = { + notifications: service, + } as any; + processor = new PushNotificationToUsersMessageProcessor(); }); afterEach(() => { @@ -149,7 +157,8 @@ describe("The PushNotificationToUsersMessageProcessor class", () => { await processor.process(message); - expect(service.channelPreferences.getChannelPreferencesForUsers).not.toBeCalled; + expect(gr.services.notifications.channelPreferences.getChannelPreferencesForUsers).not + .toBeCalled; done(); }); @@ -159,7 +168,8 @@ describe("The PushNotificationToUsersMessageProcessor class", () => { await processor.process(message); - expect(service.channelPreferences.getChannelPreferencesForUsers).not.toBeCalled; + expect(gr.services.notifications.channelPreferences.getChannelPreferencesForUsers).not + .toBeCalled; done(); }); @@ -169,7 +179,8 @@ describe("The PushNotificationToUsersMessageProcessor class", () => { await processor.process(message); - expect(service.channelPreferences.getChannelPreferencesForUsers).not.toBeCalled; + expect(gr.services.notifications.channelPreferences.getChannelPreferencesForUsers).not + .toBeCalled; done(); }); @@ -223,8 +234,8 @@ describe("The PushNotificationToUsersMessageProcessor class", () => { await processor.process(message); - expect(getChannelPreferencesForUsers).toBeCalledWith(channel, users, { lessThan }); - expect(service.badges.save).toBeCalledTimes(2); + expect(getChannelPreferencesForUsers).toBeCalledWith(channel, users, { lessThan }, undefined); + expect(gr.services.notifications.badges.save).toBeCalledTimes(2); expect(pubsubService.publish).toBeCalledTimes(2); done(); diff --git a/twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts b/twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts new file mode 100644 index 0000000000..efe61b4e29 --- /dev/null +++ b/twake/backend/node/test/unit/services/previews/services/files/processing/video.test.ts @@ -0,0 +1,176 @@ +import { describe, expect, it, jest, beforeEach, afterEach, afterAll } from "@jest/globals"; +import { generateVideoPreview } from "../../../../../../../src/services/previews/services/files/processing/video"; +import ffmpeg, { ffprobe } from "fluent-ffmpeg"; +import { cleanFiles, getTmpFile } from "../../../../../../../src/services/previews/utils"; +import fs from "fs"; + +jest.mock("fluent-ffmpeg"); +jest.mock("../../../../../../../src/services/previews/utils"); + +const ffmpegMock = { + screenshot: jest.fn().mockReturnValue({ + on: function (e, cb) { + cb(); + return this; + }, + }), +}; + +beforeEach(() => { + jest.spyOn(fs, "statSync").mockReturnValue({ size: 1 } as any); + (ffmpeg as any).mockImplementation(() => ffmpegMock); + (cleanFiles as any).mockImplementation(() => jest.fn()); + (getTmpFile as any).mockImplementation(() => "/tmp/file"); + (ffprobe as any).mockImplementation((i, cb) => { + cb(null, { + streams: [ + { + width: 320, + height: 240, + }, + ], + }); + }); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +describe("the generateVideoPreview function", () => { + it("should return a promise", () => { + const result = generateVideoPreview([]); + expect(result).toBeInstanceOf(Promise); + }); + + it("should attempt to create a screenshot using ffmpeg", async () => { + await generateVideoPreview(["/foo/bar"]); + expect(ffmpeg as any).toBeCalledWith("/foo/bar"); + }); + + it("should call ffmpeg screenshot method with the original video dimentions", async () => { + (getTmpFile as any).mockImplementation(() => "/tmp/some-random-file"); + (ffprobe as any).mockImplementation((i, cb) => { + cb(null, { + streams: [ + { + width: 500, + height: 500, + }, + ], + }); + }); + + await generateVideoPreview(["/foo/bar"]); + expect(ffmpegMock.screenshot).toBeCalledWith({ + count: 1, + filename: "some-random-file.jpg", + folder: "/tmp", + timemarks: ["0"], + size: "500x500", + }); + }); + + it("should attempt to generate a temporary file", async () => { + await generateVideoPreview(["/foo/bar"]); + + expect(getTmpFile).toBeCalled(); + }); + + it("should attempt to clean up the temporary file in case of errors", async () => { + const expectedError = new Error("failed to generate video preview: Error: foo"); + (ffmpeg as any).mockImplementation(() => { + throw new Error("foo"); + }); + + (ffprobe as any).mockImplementation((i, cb) => { + cb(null, { + streams: [ + { + width: 500, + height: 500, + }, + ], + }); + }); + + await expect(generateVideoPreview(["/foo/bar"])).rejects.toThrow(expectedError); + + expect(cleanFiles).toBeCalledWith(["/tmp/file.jpg"]); + }); + + it("should return the thumbnail information", async () => { + const result = await generateVideoPreview(["/foo/bar"]); + expect(result).toEqual([ + { + width: 320, + height: 240, + type: "image/jpg", + size: 1, + path: "/tmp/file.jpg", + }, + ]); + }); + + it("should generate thumbnails for multiple files", async () => { + const result = await generateVideoPreview(["/foo/bar", "/foo/baz", "/foo/tar"]); + expect(result).toHaveLength(3); + }); + + it("should use ffprobe to get the video dimensions", async () => { + await generateVideoPreview(["/foo/bar"]); + expect(ffprobe).toBeCalledWith("/foo/bar", expect.any(Function)); + }); + + it("should use 1080p as the maximum video dimensions", async () => { + (ffprobe as any).mockImplementation((i, cb) => { + cb(null, { + streams: [ + { + width: 5000, + height: 5000, + }, + ], + }); + }); + + const result = await generateVideoPreview(["/foo/bar"]); + expect(result).toEqual([ + { + width: 1920, + height: 1080, + type: "image/jpg", + size: 1, + path: "/tmp/file.jpg", + }, + ]); + }); + + it("should use 320x240 as the minimum video dimensions", async () => { + (ffprobe as any).mockImplementation((i, cb) => { + cb(null, { + streams: [ + { + width: 320, + height: 180, + }, + ], + }); + }); + + const result = await generateVideoPreview(["/foo/bar"]); + expect(result).toEqual([ + { + width: 320, + height: 240, + type: "image/jpg", + size: 1, + path: "/tmp/file.jpg", + }, + ]); + }); +}); diff --git a/twake/backend/node/test/unit/services/previews/services/links/processing/images.test.ts b/twake/backend/node/test/unit/services/previews/services/links/processing/images.test.ts new file mode 100644 index 0000000000..c3b0550bc1 --- /dev/null +++ b/twake/backend/node/test/unit/services/previews/services/links/processing/images.test.ts @@ -0,0 +1,61 @@ +import { describe, expect, it, jest, beforeEach, afterEach, afterAll } from "@jest/globals"; +import { generateImageUrlPreview } from "../../../../../../../src/services/previews/services/links/processing/image"; + +import getFavicons from "get-website-favicon"; +import imageProbe from "probe-image-size"; + +jest.mock("get-website-favicon"); +jest.mock("probe-image-size"); + +beforeEach(() => { + (imageProbe as any).mockImplementation(() => ({ + width: 320, + height: 240, + })); + + (getFavicons as any).mockImplementation(() => ({ + icons: [ + { + src: "http://foo.bar/favicon.ico", + }, + ], + })); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +describe("the generateImageUrlPreview function", () => { + it("should return a promise", () => { + const result = generateImageUrlPreview("http://foo.bar"); + expect(result).toBeInstanceOf(Promise); + }); + + it("should generate a preview for a given image url", async () => { + const result = await generateImageUrlPreview("https://foo.bar/image.jpg"); + expect(result).toEqual({ + title: "image.jpg", // title should be the file name + domain: "foo.bar", + favicon: "http://foo.bar/favicon.ico", + url: "https://foo.bar/image.jpg", + img_height: 240, + img_width: 320, + description: null, + img: "https://foo.bar/image.jpg", + }); + }); + + it("should return nothing in case of error", async () => { + (imageProbe as any).mockImplementation(() => { + throw new Error("failed to probe image"); + }); + + const result = await generateImageUrlPreview("https://foo.bar/image.jpg"); + expect(result).toBeUndefined(); + }); +}); diff --git a/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts b/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts new file mode 100644 index 0000000000..30eaa5850c --- /dev/null +++ b/twake/backend/node/test/unit/services/previews/services/links/processing/links.test.ts @@ -0,0 +1,186 @@ +import { describe, expect, it, jest, beforeEach, afterEach, afterAll } from "@jest/globals"; +import { generateLinkPreview } from "../../../../../../../src/services/previews/services/links/processing/link"; +import { parser } from "html-metadata-parser"; +import getFavicons from "get-website-favicon"; +import imageProbe from "probe-image-size"; + +jest.mock("html-metadata-parser"); +jest.mock("get-website-favicon"); +jest.mock("probe-image-size"); + +beforeEach(() => { + (imageProbe as any).mockImplementation(() => ({ + width: 320, + height: 240, + })); + + (getFavicons as any).mockImplementation(() => ({ + icons: [ + { + src: "http://foo.bar/favicon.ico", + }, + ], + })); + + (parser as any).mockImplementation(() => ({ + og: { + title: "Foo", + description: "Bar", + image: "http://foo.bar/image.jpg", + }, + meta: { + title: "Foo", + description: "Bar", + image: "http://foo.bar/image1.jpg", + }, + images: ["http://foo.bar/image2.jpg"], + })); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +describe("the generateLinkPreview service", () => { + it("should return a promise", () => { + const result = generateLinkPreview("http://foo.bar"); + expect(result).toBeInstanceOf(Promise); + }); + + it("should return a promise that resolves to a preview", async () => { + const result = await generateLinkPreview("https://foo.bar"); + expect(result).toEqual({ + title: "Foo", + description: "Bar", + img: "http://foo.bar/image.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + url: "https://foo.bar", + }); + }); + + it("should return a promise that resolves to undefined if no previews are found", async () => { + (parser as any).mockImplementation(() => { + throw new Error("failed to parse"); + }); + (getFavicons as any).mockImplementation(() => []); + (imageProbe as any).mockImplementation(() => ({})); + + const result = await generateLinkPreview("https://foo.bar"); + expect(result).toBeUndefined(); + }); + + it("should use og information as first choice", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + image: "http://foo.bar/test.jpg", + }, + meta: { + title: "test2", + description: "test2", + image: "http://foo.bar/test2.jpg", + }, + images: ["http://foo.bar/test3.jpg"], + })); + + const result = await generateLinkPreview("https://foo.bar"); + expect(result).toEqual({ + title: "test", + description: "test", + img: "http://foo.bar/test.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + url: "https://foo.bar", + }); + }); + + it("should use meta information as second choice", async () => { + (parser as any).mockImplementation(() => ({ + meta: { + title: "test2", + description: "test2", + image: "http://foo.bar/test2.jpg", + }, + images: [], + })); + + const result = await generateLinkPreview("https://foo.bar"); + expect(result).toEqual({ + title: "test2", + description: "test2", + img: "http://foo.bar/test2.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + url: "https://foo.bar", + }); + }); + + it("should use the first image found in the url when none are present in the og or meta information", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + }, + meta: { + title: "test2", + description: "test2", + }, + images: ["http://foo.bar/test3.jpg", "http://foo.bar/test4.jpg"], + })); + + const result = await generateLinkPreview("https://foo.bar"); + expect(result).toEqual({ + title: "test", + description: "test", + img: "http://foo.bar/test3.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + url: "https://foo.bar", + }); + }); + + it("shouldn't attempt to probe for image size when none are found", async () => { + (parser as any).mockImplementation(() => ({ + og: { + title: "test", + description: "test", + }, + meta: { + title: "test2", + description: "test2", + }, + images: [], + })); + + await generateLinkPreview("https://foo.bar"); + expect(imageProbe).not.toHaveBeenCalled(); + }); + + it("should strip www from the domain", async () => { + const result = await generateLinkPreview("https://www.foo.bar"); + expect(result).toEqual({ + title: "Foo", + description: "Bar", + img: "http://foo.bar/image.jpg", + favicon: "http://foo.bar/favicon.ico", + img_width: 320, + img_height: 240, + domain: "foo.bar", + url: "https://www.foo.bar", + }); + }); +}); diff --git a/twake/backend/node/test/unit/services/previews/services/links/processing/service.test.ts b/twake/backend/node/test/unit/services/previews/services/links/processing/service.test.ts new file mode 100644 index 0000000000..b6293649ae --- /dev/null +++ b/twake/backend/node/test/unit/services/previews/services/links/processing/service.test.ts @@ -0,0 +1,109 @@ +import { + describe, + expect, + it, + jest, + beforeEach, + afterEach, + afterAll, + beforeAll, +} from "@jest/globals"; +import { LinkPreviewProcessService } from "../../../../../../../src/services/previews/services/links/processing/service"; +import { generateLinkPreview } from "../../../../../../../src/services/previews/services/links/processing/link"; +import { generateImageUrlPreview } from "../../../../../../../src/services/previews/services/links/processing/image"; +import axios from "axios"; + +jest.mock("axios"); +jest.mock("../../../../../../../src/services/previews/services/links/processing/link"); +jest.mock("../../../../../../../src/services/previews/services/links/processing/image"); + +let service: LinkPreviewProcessService; + +beforeEach(async () => { + (axios as any).mockImplementation(() => ({ + headers: { + "content-type": "text/html", + }, + })); + + (generateLinkPreview as any).mockImplementation(() => ({ + title: "Foo", + description: "Bar", + img: "http://foo.bar/image.jpg", + favicon: "http://foo.bar/favicon.ico", + })); + + (generateImageUrlPreview as any).mockImplementation(() => ({ + title: "image.jpg", + description: null, + img: "http://foo.bar/image.jpg", + favicon: "http://foo.bar/favicon.ico", + })); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +afterAll(() => { + jest.restoreAllMocks(); +}); + +beforeAll(async () => { + service = await new LinkPreviewProcessService().init(); +}); + +describe("the LinkPreviewProcessService service", () => { + it("should return a promise", () => { + const result = service.generatePreviews(["http://foo.bar"]); + expect(result).toBeInstanceOf(Promise); + }); + + it("should call generateLinkPreview when it's a html page", async () => { + (axios as any).mockImplementation(() => ({ + headers: { + "content-type": "text/html", + }, + })); + + await service.generatePreviews(["http://foo.bar"]); + expect(generateLinkPreview).toHaveBeenCalled(); + }); + + it("should call generateImageUrlPreview when it's an image", async () => { + (axios as any).mockImplementation(() => ({ + headers: { + "content-type": "image/jpeg", + }, + })); + + await service.generatePreviews(["http://foo.bar/image.jpg"]); + expect(generateImageUrlPreview).toHaveBeenCalled(); + }); + + it("should skip if the url content is not supported", async () => { + (axios as any).mockImplementation(() => ({ + headers: { + "content-type": "application/json", + }, + })); + + await service.generatePreviews(["http://foo.bar"]); + expect(generateLinkPreview).not.toHaveBeenCalled(); + expect(generateImageUrlPreview).not.toHaveBeenCalled(); + }); + + // should filter null values + it("should filter null values", async () => { + (axios as any).mockImplementation(() => ({ + headers: { + "content-type": "text/html", + }, + })); + + (generateLinkPreview as any).mockImplementation(() => null); + + const result = await service.generatePreviews(["http://foo.bar", "http://foo.xyz"]); + expect(result).toEqual([]); + }); +}); diff --git a/twake/backend/node/yarn.lock b/twake/backend/node/yarn.lock index 909484e654..a1f5af3dcc 100644 --- a/twake/backend/node/yarn.lock +++ b/twake/backend/node/yarn.lock @@ -2,104 +2,137 @@ # yarn lockfile v1 +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== + dependencies: + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" + "@babel/code-frame@7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" + 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.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz" - integrity sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw== - dependencies: - "@babel/highlight" "^7.14.5" - -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.7", "@babel/compat-data@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz" - integrity sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA== - -"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.7.5": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz" - integrity sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.0" - "@babel/helper-module-transforms" "^7.15.0" - "@babel/helpers" "^7.14.8" - "@babel/parser" "^7.15.0" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== + dependencies: + "@babel/highlight" "^7.18.6" + +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.6.tgz" + integrity sha512-tzulrgDT0QD6U7BJ4TKVk2SDDg7wlP39P9yAx1RfLy7vP/7rsDRlWVfbWxElslu56+r7QOhB2NSDsabYYruoZQ== + +"@babel/compat-data@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" + integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== + +"@babel/core@^7.1.0", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.7.5": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.18.6.tgz" + integrity sha512-cQbWBpxcbbs/IUredIPkHiAGULLV8iwgNRMFzvbhEXISp4f3rUUXE5+TIw6KwUWUR3DwyI6gmBRnmAtYaWehwQ== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helpers" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.1.2" + json5 "^2.2.1" semver "^6.3.0" - source-map "^0.5.0" -"@babel/generator@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz" - integrity sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ== +"@babel/generator@^7.18.10": + version "7.18.12" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.12.tgz#fa58daa303757bd6f5e4bbca91b342040463d9f4" + integrity sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg== dependencies: - "@babel/types" "^7.15.0" + "@babel/types" "^7.18.10" + "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz" - integrity sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA== +"@babel/generator@^7.18.6": + version "7.18.7" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.18.7.tgz" + integrity sha512-shck+7VLlY72a2w9c3zYWuE1pwOKEiQHV7GTUbSnhyl5eu3i04t30tBY82ZRWrDfo3gkakCFtevExnxbkf2a3A== dependencies: - "@babel/types" "^7.14.5" + "@babel/types" "^7.18.7" + "@jridgewell/gen-mapping" "^0.3.2" + jsesc "^2.5.1" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz" - integrity sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w== +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.6.tgz" + integrity sha512-KT10c1oWEpmrIRYnthbzHgoOf6B+Xd6a5yhdbNtdhtG7aO1or5HViuf1TQR36xY/QprXA5nvxO6nAjhJ4y38jw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.14.5" - "@babel/types" "^7.14.5" + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.6" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.14.5", "@babel/helper-compilation-targets@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz" - integrity sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A== +"@babel/helper-compilation-targets@^7.13.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf" + integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg== dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + "@babel/compat-data" "^7.18.8" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.20.2" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.14.5", "@babel/helper-create-class-features-plugin@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.15.0.tgz" - integrity sha512-MdmDXgvTIi4heDVX/e9EFfeGpugqm9fobBVg/iioE8kueXrOHdRDe36FAY7SnE9xXLVeYCoJR/gdrBEIHRC83Q== +"@babel/helper-compilation-targets@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.6.tgz" + integrity sha512-vFjbfhNCzqdeAtZflUFrG5YIFqGTqsctrtkZ1D/NB0mDW9TwW3GmmUepYY4G9wCET5rY5ugz4OGTcLd614IzQg== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-member-expression-to-functions" "^7.15.0" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.0" - "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/compat-data" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.20.2" + semver "^6.3.0" -"@babel/helper-create-regexp-features-plugin@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz" - integrity sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A== +"@babel/helper-create-class-features-plugin@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.6.tgz" + integrity sha512-YfDzdnoxHGV8CzqHGyCbFvXg5QESPFkXlHtvdCkesLjjVMT2Adxe4FGUR5ChIb3DxSaXO12iIOCWoXdsUVwnqw== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - regexpu-core "^4.7.1" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" -"@babel/helper-define-polyfill-provider@^0.2.2": - version "0.2.3" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz" - integrity sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew== +"@babel/helper-create-regexp-features-plugin@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz" + integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.3.1": + version "0.3.1" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz" + integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA== dependencies: "@babel/helper-compilation-targets" "^7.13.0" "@babel/helper-module-imports" "^7.12.13" @@ -110,718 +143,768 @@ resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz" - integrity sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz" - integrity sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ== - dependencies: - "@babel/helper-get-function-arity" "^7.14.5" - "@babel/template" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helper-get-function-arity@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz" - integrity sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-hoist-variables@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz" - integrity sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-member-expression-to-functions@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz" - integrity sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg== - dependencies: - "@babel/types" "^7.15.0" - -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz" - integrity sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-module-transforms@^7.14.5", "@babel/helper-module-transforms@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz" - integrity sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg== - dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-replace-supers" "^7.15.0" - "@babel/helper-simple-access" "^7.14.8" - "@babel/helper-split-export-declaration" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.9" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - -"@babel/helper-optimise-call-expression@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz" - integrity sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA== - dependencies: - "@babel/types" "^7.14.5" - -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-remap-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz" - integrity sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A== - dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-wrap-function" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/helper-replace-supers@^7.14.5", "@babel/helper-replace-supers@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz" - integrity sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.15.0" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" - -"@babel/helper-simple-access@^7.14.8": - version "7.14.8" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz" - integrity sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg== - dependencies: - "@babel/types" "^7.14.8" - -"@babel/helper-skip-transparent-expression-wrappers@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz" - integrity sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ== - dependencies: - "@babel/types" "^7.14.5" +"@babel/helper-environment-visitor@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.6.tgz" + integrity sha512-8n6gSfn2baOY+qlp+VSzsosjCVGFqWKmDF0cCWOybh52Dw3SEyoWR1KrhMJASjLwIEkkAufZ0xvr+SxLHSpy2Q== + +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== + +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.6.tgz" + integrity sha512-0mWMxV1aC97dhjCah5U5Ua7668r5ZmSC2DLfH2EZnf9c3/dHZKiFa5pRLMH5tjSl471tY6496ZWk/kjNONBxhw== + dependencies: + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0" + integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A== + dependencies: + "@babel/template" "^7.18.6" + "@babel/types" "^7.18.9" + +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-member-expression-to-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.6.tgz" + integrity sha512-CeHxqwwipekotzPDUuJOfIMtcIHBuc7WAzLmTYWctVigqS5RktNMQ5bEwQSuGewzYnCtTWa3BARXeiLxDTv+Ng== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-module-transforms@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.6.tgz" + integrity sha512-L//phhB4al5uucwzlimruukHB3jRd5JGClwRMD/ROrVjXfLqovYnvQrK/JK36WYyVwGGO7OD3kMyVTjx+WVPhw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz" + integrity sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg== + +"@babel/helper-plugin-utils@^7.13.0": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f" + integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w== + +"@babel/helper-remap-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz" + integrity sha512-z5wbmV55TveUPZlCLZvxWHtrjuJd+8inFhk7DG0WW87/oJuGDcjDiu7HIvGcpf5464L6xKCg3vNkmlVVz9hwyQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-wrap-function" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-replace-supers@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.6.tgz" + integrity sha512-fTf7zoXnUGl9gF25fXCWE26t7Tvtyn6H4hkLSYhATwJvw2uYxd3aoXplMSe0g9XbwK7bmxNes7+FGO0rB/xC0g== + dependencies: + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-member-expression-to-functions" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helper-simple-access@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" + integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.6.tgz" + integrity sha512-4KoLhwGS9vGethZpAhYnMejWkX64wsnHPDwvOsKWU6Fg4+AlK2Jz3TyjQLMEPvz+1zemi/WBdkYxCD0bAfIkiw== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" + integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== + +"@babel/helper-validator-identifier@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz" + integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.6.tgz" + integrity sha512-I5/LZfozwMNbwr/b1vhhuYD+J/mU+gfGAj5td7l5Rv9WYmH6i3Om69WGKNmlIpsVW/mF6O5bvTKbvDQZVgjqOw== + dependencies: + "@babel/helper-function-name" "^7.18.6" + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/helpers@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.6.tgz" + integrity sha512-vzSiiqbQOghPngUYt/zWGvK3LAsPhz55vc9XNN0xAl2gV4ieShI2OQli5duxWHD+72PZPTKAcfcZDE1Cwc5zsQ== + dependencies: + "@babel/template" "^7.18.6" + "@babel/traverse" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + chalk "^2.0.0" + js-tokens "^4.0.0" -"@babel/helper-split-export-declaration@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz" - integrity sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA== - dependencies: - "@babel/types" "^7.14.5" +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.18.6.tgz" + integrity sha512-uQVSa9jJUe/G/304lXspfWVpKpK4euFLgGiMQFOCpM/bgcAdeoHwi/OQz23O9GK2osz26ZiXRRV9aV+Yl1O8tw== -"@babel/helper-validator-identifier@^7.14.5", "@babel/helper-validator-identifier@^7.14.9": - version "7.14.9" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz" - integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g== +"@babel/parser@^7.18.11": + version "7.18.11" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9" + integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ== -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helper-wrap-function@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz" - integrity sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.14.5" - "@babel/types" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/helpers@^7.14.8": - version "7.15.3" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz" - integrity sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.6.tgz" + integrity sha512-Udgu8ZRgrBrttVz6A0EVL0SJ1z+RLbIeqsu632SA1hf0awEppD6TvdznoH+orIF8wtFFAV/Enmw9Y+9oV8TQcw== dependencies: - "@babel/template" "^7.14.5" - "@babel/traverse" "^7.15.0" - "@babel/types" "^7.15.0" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" -"@babel/highlight@^7.10.4", "@babel/highlight@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz" - integrity sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg== +"@babel/plugin-proposal-async-generator-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.6.tgz" + integrity sha512-WAz4R9bvozx4qwf74M+sfqPMKfSqwM0phxPTR6iJIi8robgzXwkEgmeJG1gEKhm6sDqT/U9aV3lfcqybIpev8w== dependencies: - "@babel/helper-validator-identifier" "^7.14.5" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.5", "@babel/parser@^7.15.0": - version "7.15.3" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz" - integrity sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA== - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz" - integrity sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - -"@babel/plugin-proposal-async-generator-functions@^7.14.9": - version "7.14.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.9.tgz" - integrity sha512-d1lnh+ZnKrFKwtTYdw320+sQWCTwgkB9fmUhNXRADA4akR6wLjaruSGnIEUjpt9HCOwTr4ynFTKu19b7rFRpmw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz" - integrity sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg== +"@babel/plugin-proposal-class-properties@^7.10.4", "@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz" - integrity sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg== +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-proposal-decorators@^7.10.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz" - integrity sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-decorators" "^7.14.5" - -"@babel/plugin-proposal-dynamic-import@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz" - integrity sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.6.tgz" + integrity sha512-gAdhsjaYmiZVxx5vTMiRfj31nB7LhwBJFMSLzeDxc7X4tKLixup0+k9ughn0RcpBrv9E3PBaXJW7jF5TCihAOg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/plugin-syntax-decorators" "^7.18.6" + +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz" - integrity sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA== +"@babel/plugin-proposal-export-namespace-from@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.6.tgz" + integrity sha512-zr/QcUlUo7GPo6+X1wC98NJADqmy5QTFWWhqeQWiki4XHafJtLl/YMGkmRB2szDD2IYJCCdBTd4ElwhId9T7Xw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz" - integrity sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ== +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz" - integrity sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw== +"@babel/plugin-proposal-logical-assignment-operators@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.6.tgz" + integrity sha512-zMo66azZth/0tVd7gmkxOkOjs2rpHyhpcFo565PUP37hSp6hSd9uUKIfTDFMz58BwqgQKhJ9YxtM5XddjXVn+Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz" - integrity sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz" - integrity sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg== +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.14.7": - version "7.14.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz" - integrity sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g== +"@babel/plugin-proposal-object-rest-spread@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.6.tgz" + integrity sha512-9yuM6wr4rIsKa1wlUAbZEazkCrgw2sMPEXCr4Rnwetu7cEW1NydkCWytLuYletbf8vFxdJxFhwEZqMpOx2eZyw== dependencies: - "@babel/compat-data" "^7.14.7" - "@babel/helper-compilation-targets" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.14.5" + "@babel/plugin-transform-parameters" "^7.18.6" -"@babel/plugin-proposal-optional-catch-binding@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz" - integrity sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ== +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz" - integrity sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ== +"@babel/plugin-proposal-optional-chaining@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz" + integrity sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz" - integrity sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g== +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-private-property-in-object@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz" - integrity sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q== +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz" + integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-create-class-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.14.5", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz" - integrity sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q== +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-bigint@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz" - integrity sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw== +"@babel/plugin-syntax-decorators@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.18.6.tgz" + integrity sha512-fqyLgjcxf/1yhyZ6A+yo1u9gJ7eleFQod2lkaUsF9DQ7sbbY3Ligym3L0+I2c0WmqNKDpoD9UTb1AKP3qRMOAQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-import-assertions@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz" + integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz" - integrity sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q== +"@babel/plugin-syntax-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz" + integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz" - integrity sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A== +"@babel/plugin-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz" - integrity sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA== +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: - "@babel/helper-module-imports" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.14.5" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" -"@babel/plugin-transform-block-scoped-functions@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz" - integrity sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ== +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-block-scoping@^7.14.5": - version "7.15.3" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.15.3.tgz" - integrity sha512-nBAzfZwZb4DkaGtOes1Up1nOAp9TDRRFw4XBzBBSG9QK7KVFmYzgj9o9sbPv7TX5ofL4Auq4wZnxCoPnI/lz2Q== +"@babel/plugin-transform-block-scoping@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.6.tgz" + integrity sha512-pRqwb91C42vs1ahSAWJkxOxU1RHWDn16XAa6ggQ72wjLlWyYeAcLvTtE0aM8ph3KNydy9CQF2nLYcjq1WysgxQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-classes@^7.14.9": - version "7.14.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.9.tgz" - integrity sha512-NfZpTcxU3foGWbl4wxmZ35mTsYJy8oQocbeIMoDAGGFarAmSQlL+LWMkDx/tj6pNotpbX3rltIA4dprgAPOq5A== +"@babel/plugin-transform-classes@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.6.tgz" + integrity sha512-XTg8XW/mKpzAF3actL554Jl/dOYoJtv3l8fxaEczpgz84IeeVf+T1u2CSvPHuZbt0w3JkIx4rdn/MRQI7mo0HQ== dependencies: - "@babel/helper-annotate-as-pure" "^7.14.5" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-optimise-call-expression" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" - "@babel/helper-split-export-declaration" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz" - integrity sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg== +"@babel/plugin-transform-computed-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.6.tgz" + integrity sha512-9repI4BhNrR0KenoR9vm3/cIc1tSBIo+u1WVjKCAynahj25O8zfbiE6JtAtHPGQSs4yZ+bA8mRasRP+qc+2R5A== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-destructuring@^7.14.7": - version "7.14.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz" - integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw== +"@babel/plugin-transform-destructuring@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.6.tgz" + integrity sha512-tgy3u6lRp17ilY8r1kP4i2+HDUwxlVqq3RTc943eAWSzGgpU1qhiKpqZ5CMyHReIYPHdo3Kg8v8edKtDqSVEyQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-dotall-regex@^7.14.5", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz" - integrity sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw== +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-duplicate-keys@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz" - integrity sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A== +"@babel/plugin-transform-duplicate-keys@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.6.tgz" + integrity sha512-NJU26U/208+sxYszf82nmGYqVF9QN8py2HFTblPT9hbawi8+1C5a9JubODLTGFuT0qlkqVinmkwOD13s0sZktg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-exponentiation-operator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz" - integrity sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA== +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-for-of@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz" - integrity sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA== +"@babel/plugin-transform-for-of@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.6.tgz" + integrity sha512-WAjoMf4wIiSsy88KmG7tgj2nFdEK7E46tArVtcgED7Bkj6Fg/tG5SbvNIOKxbFS2VFgNh6+iaPswBeQZm4ox8w== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-function-name@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz" - integrity sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ== +"@babel/plugin-transform-function-name@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.6.tgz" + integrity sha512-kJha/Gbs5RjzIu0CxZwf5e3aTTSlhZnHMT8zPWnJMjNpLOUgqevg+PN5oMH68nMCXnfiMo4Bhgxqj59KHTlAnA== dependencies: - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz" - integrity sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A== +"@babel/plugin-transform-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.6.tgz" + integrity sha512-x3HEw0cJZVDoENXOp20HlypIHfl0zMIhMVZEBVTfmqbObIpsMxMbmU5nOEO8R7LYT+z5RORKPlTI5Hj4OsO9/Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-member-expression-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz" - integrity sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q== +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-modules-amd@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz" - integrity sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g== +"@babel/plugin-transform-modules-amd@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz" + integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.15.0.tgz" - integrity sha512-3H/R9s8cXcOGE8kgMlmjYYC9nqr5ELiPkJn4q0mypBrjhYQoc+5/Maq69vV4xRPWnkzZuwJPf5rArxpB/35Cig== +"@babel/plugin-transform-modules-commonjs@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz" + integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== dependencies: - "@babel/helper-module-transforms" "^7.15.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.14.8" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-simple-access" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz" - integrity sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA== +"@babel/plugin-transform-modules-systemjs@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.6.tgz" + integrity sha512-UbPYpXxLjTw6w6yXX2BYNxF3p6QY225wcTkfQCy3OMnSlS/C3xGtwUjEzGkldb/sy6PWLiCQ3NbYfjWUTI3t4g== dependencies: - "@babel/helper-hoist-variables" "^7.14.5" - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.14.5" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-identifier" "^7.18.6" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz" - integrity sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA== +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: - "@babel/helper-module-transforms" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.14.9": - version "7.14.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.9.tgz" - integrity sha512-l666wCVYO75mlAtGFfyFwnWmIXQm3kSH0C3IRnJqWcZbWkoihyAdDhFm2ZWaxWTqvBvhVFfJjMRQ0ez4oN1yYA== +"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz" + integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-new-target@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz" - integrity sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ== +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-object-super@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz" - integrity sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg== +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" -"@babel/plugin-transform-parameters@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz" - integrity sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA== +"@babel/plugin-transform-parameters@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.6.tgz" + integrity sha512-FjdqgMv37yVl/gwvzkcB+wfjRI8HQmc5EgOG9iGNvUY1ok+TjsoaMP7IqCDZBhkFcM5f3OPVMs6Dmp03C5k4/A== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-property-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz" - integrity sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw== +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-regenerator@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz" - integrity sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg== +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz" + integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: - regenerator-transform "^0.14.2" + "@babel/helper-plugin-utils" "^7.18.6" + regenerator-transform "^0.15.0" -"@babel/plugin-transform-reserved-words@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz" - integrity sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg== +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-shorthand-properties@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz" - integrity sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g== +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-spread@^7.14.6": - version "7.14.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz" - integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag== +"@babel/plugin-transform-spread@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.6.tgz" + integrity sha512-ayT53rT/ENF8WWexIRg9AiV9h0aIteyWn5ptfZTZQrjk/+f3WdrJGCY4c9wcgl2+MKkKPhzbYp97FTsquZpDCw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" -"@babel/plugin-transform-sticky-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz" - integrity sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A== +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-template-literals@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz" - integrity sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg== +"@babel/plugin-transform-template-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.6.tgz" + integrity sha512-UuqlRrQmT2SWRvahW46cGSany0uTlcj8NYOS5sRGYi8FxPYPoLd5DDmMd32ZXEj2Jq+06uGVQKHxa/hJx2EzKw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-typeof-symbol@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz" - integrity sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw== +"@babel/plugin-transform-typeof-symbol@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.6.tgz" + integrity sha512-7m71iS/QhsPk85xSjFPovHPcH3H9qeyzsujhTc+vcdnsXavoWYJ74zx0lP5RhpC5+iDnVLO+PPMHzC11qels1g== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-typescript@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.15.0.tgz" - integrity sha512-WIIEazmngMEEHDaPTx0IZY48SaAmjVWe3TRSX7cmJXn0bEv9midFzAjxiruOWYIVf5iQ10vFx7ASDpgEO08L5w== +"@babel/plugin-transform-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.6.tgz" + integrity sha512-ijHNhzIrLj5lQCnI6aaNVRtGVuUZhOXFLRVFs7lLrkXTHip4FKty5oAuQdk4tywG0/WjXmjTfQCWmuzrvFer1w== dependencies: - "@babel/helper-create-class-features-plugin" "^7.15.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-typescript" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-syntax-typescript" "^7.18.6" -"@babel/plugin-transform-unicode-escapes@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz" - integrity sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA== +"@babel/plugin-transform-unicode-escapes@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.6.tgz" + integrity sha512-XNRwQUXYMP7VLuy54cr/KS/WeL3AZeORhrmeZ7iewgu+X2eBqmpaLI/hzqr9ZxCeUoq0ASK4GUzSM0BDhZkLFw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-unicode-regex@^7.14.5": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz" - integrity sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw== +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.14.5" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/preset-env@^7.11.5": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.15.0.tgz" - integrity sha512-FhEpCNFCcWW3iZLg0L2NPE9UerdtsCR6ZcsGHUX6Om6kbCQeL5QZDqFDmeNHC6/fy6UH3jEge7K4qG5uC9In0Q== - dependencies: - "@babel/compat-data" "^7.15.0" - "@babel/helper-compilation-targets" "^7.15.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-async-generator-functions" "^7.14.9" - "@babel/plugin-proposal-class-properties" "^7.14.5" - "@babel/plugin-proposal-class-static-block" "^7.14.5" - "@babel/plugin-proposal-dynamic-import" "^7.14.5" - "@babel/plugin-proposal-export-namespace-from" "^7.14.5" - "@babel/plugin-proposal-json-strings" "^7.14.5" - "@babel/plugin-proposal-logical-assignment-operators" "^7.14.5" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5" - "@babel/plugin-proposal-numeric-separator" "^7.14.5" - "@babel/plugin-proposal-object-rest-spread" "^7.14.7" - "@babel/plugin-proposal-optional-catch-binding" "^7.14.5" - "@babel/plugin-proposal-optional-chaining" "^7.14.5" - "@babel/plugin-proposal-private-methods" "^7.14.5" - "@babel/plugin-proposal-private-property-in-object" "^7.14.5" - "@babel/plugin-proposal-unicode-property-regex" "^7.14.5" + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.6.tgz" + integrity sha512-WrthhuIIYKrEFAwttYzgRNQ5hULGmwTj+D6l7Zdfsv5M7IWV/OZbUfbeL++Qrzx1nVJwWROIFhCHRYQV4xbPNw== + dependencies: + "@babel/compat-data" "^7.18.6" + "@babel/helper-compilation-targets" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-async-generator-functions" "^7.18.6" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.6" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.6" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.18.6" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.6" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.18.6" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -831,50 +914,50 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.14.5" - "@babel/plugin-transform-async-to-generator" "^7.14.5" - "@babel/plugin-transform-block-scoped-functions" "^7.14.5" - "@babel/plugin-transform-block-scoping" "^7.14.5" - "@babel/plugin-transform-classes" "^7.14.9" - "@babel/plugin-transform-computed-properties" "^7.14.5" - "@babel/plugin-transform-destructuring" "^7.14.7" - "@babel/plugin-transform-dotall-regex" "^7.14.5" - "@babel/plugin-transform-duplicate-keys" "^7.14.5" - "@babel/plugin-transform-exponentiation-operator" "^7.14.5" - "@babel/plugin-transform-for-of" "^7.14.5" - "@babel/plugin-transform-function-name" "^7.14.5" - "@babel/plugin-transform-literals" "^7.14.5" - "@babel/plugin-transform-member-expression-literals" "^7.14.5" - "@babel/plugin-transform-modules-amd" "^7.14.5" - "@babel/plugin-transform-modules-commonjs" "^7.15.0" - "@babel/plugin-transform-modules-systemjs" "^7.14.5" - "@babel/plugin-transform-modules-umd" "^7.14.5" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.14.9" - "@babel/plugin-transform-new-target" "^7.14.5" - "@babel/plugin-transform-object-super" "^7.14.5" - "@babel/plugin-transform-parameters" "^7.14.5" - "@babel/plugin-transform-property-literals" "^7.14.5" - "@babel/plugin-transform-regenerator" "^7.14.5" - "@babel/plugin-transform-reserved-words" "^7.14.5" - "@babel/plugin-transform-shorthand-properties" "^7.14.5" - "@babel/plugin-transform-spread" "^7.14.6" - "@babel/plugin-transform-sticky-regex" "^7.14.5" - "@babel/plugin-transform-template-literals" "^7.14.5" - "@babel/plugin-transform-typeof-symbol" "^7.14.5" - "@babel/plugin-transform-unicode-escapes" "^7.14.5" - "@babel/plugin-transform-unicode-regex" "^7.14.5" - "@babel/preset-modules" "^0.1.4" - "@babel/types" "^7.15.0" - babel-plugin-polyfill-corejs2 "^0.2.2" - babel-plugin-polyfill-corejs3 "^0.2.2" - babel-plugin-polyfill-regenerator "^0.2.2" - core-js-compat "^3.16.0" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.18.6" + "@babel/plugin-transform-classes" "^7.18.6" + "@babel/plugin-transform-computed-properties" "^7.18.6" + "@babel/plugin-transform-destructuring" "^7.18.6" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.6" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.6" + "@babel/plugin-transform-function-name" "^7.18.6" + "@babel/plugin-transform-literals" "^7.18.6" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.18.6" + "@babel/plugin-transform-modules-commonjs" "^7.18.6" + "@babel/plugin-transform-modules-systemjs" "^7.18.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.18.6" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.18.6" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.6" + "@babel/plugin-transform-typeof-symbol" "^7.18.6" + "@babel/plugin-transform-unicode-escapes" "^7.18.6" + "@babel/plugin-transform-unicode-regex" "^7.18.6" + "@babel/preset-modules" "^0.1.5" + "@babel/types" "^7.18.6" + babel-plugin-polyfill-corejs2 "^0.3.1" + babel-plugin-polyfill-corejs3 "^0.5.2" + babel-plugin-polyfill-regenerator "^0.3.1" + core-js-compat "^3.22.1" semver "^6.3.0" -"@babel/preset-modules@^0.1.4": - version "0.1.4" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== +"@babel/preset-modules@^0.1.5": + version "0.1.5" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" @@ -883,70 +966,96 @@ esutils "^2.0.2" "@babel/preset-typescript@^7.10.4": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.15.0.tgz" - integrity sha512-lt0Y/8V3y06Wq/8H/u0WakrqciZ7Fz7mwPDHWUJAXlABL5hiUG42BNlRXiELNjeWjO5rWmnNKlx+yzJvxezHow== + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-typescript" "^7.15.0" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" "@babel/runtime@^7.8.4": - version "7.15.3" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.3.tgz" - integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA== + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz" + integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ== dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.14.5", "@babel/template@^7.3.3": - version "7.14.5" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz" - integrity sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/parser" "^7.14.5" - "@babel/types" "^7.14.5" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.15.0": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz" - integrity sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw== - dependencies: - "@babel/code-frame" "^7.14.5" - "@babel/generator" "^7.15.0" - "@babel/helper-function-name" "^7.14.5" - "@babel/helper-hoist-variables" "^7.14.5" - "@babel/helper-split-export-declaration" "^7.14.5" - "@babel/parser" "^7.15.0" - "@babel/types" "^7.15.0" +"@babel/template@^7.18.6", "@babel/template@^7.3.3": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz" + integrity sha512-JoDWzPe+wgBsTTgdnIma3iHNFC7YVJoPssVBDjiHfNlyt4YcunDtcDOUmfVDfCK5MfdsaIoX9PkijPhjH3nYUw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.18.6": + version "7.18.6" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.6.tgz" + integrity sha512-zS/OKyqmD7lslOtFqbscH6gMLFYOfG1YPqCKfAW5KrTeolKqvB8UelR49Fpr6y93kYkW2Ik00mT1LOGiAGvizw== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.6" + "@babel/helper-function-name" "^7.18.6" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.6" + "@babel/types" "^7.18.6" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/traverse@^7.13.0": + version "7.18.11" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.11.tgz#3d51f2afbd83ecf9912bcbb5c4d94e3d2ddaa16f" + integrity sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.18.10" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.18.11" + "@babel/types" "^7.18.10" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.14.5", "@babel/types@^7.14.8", "@babel/types@^7.15.0", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.15.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz" - integrity sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ== +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": + version "7.18.7" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.18.7.tgz" + integrity sha512-QG3yxTcTIBoAcQmkCs+wAPYZhu7Dk9rXKacINfNbdJDNERTbLQbHGyVG8q/YGMPeCJRIhSY0+fTc5+xuh6WPSQ== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" + to-fast-properties "^2.0.0" + +"@babel/types@^7.18.10", "@babel/types@^7.18.9": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6" + integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ== dependencies: - "@babel/helper-validator-identifier" "^7.14.9" + "@babel/helper-string-parser" "^7.18.10" + "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" - resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== "@cnakazawa/watch@^1.0.3": version "1.0.4" - resolved "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== dependencies: exec-sh "^0.3.2" minimist "^1.2.0" "@elastic/elasticsearch@7": - version "7.14.0" - resolved "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.14.0.tgz" - integrity sha512-BlxqykcNtdBxo0mF7UQ1OsUxoVOOnEaeF70u2N4jpePih9paCOOotTWfFSDrtEw0TWv1CZlzCGD3TD5+8ASx8A== + version "7.17.0" + resolved "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.17.0.tgz" + integrity sha512-5QLPCjd0uLmLj1lSuKSThjNpq39f6NmlTy9ROLFwG5gjyTgpwSqufDeYG/Fm43Xs05uF7WcscoO7eguI3HuuYA== dependencies: debug "^4.3.1" hpagent "^0.1.1" @@ -955,7 +1064,7 @@ "@eslint/eslintrc@^0.4.3": version "0.4.3" - resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c" integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw== dependencies: ajv "^6.12.4" @@ -970,19 +1079,114 @@ "@fastify/ajv-compiler@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-1.1.0.tgz#5ce80b1fc8bebffc8c5ba428d5e392d0f9ed10a1" integrity sha512-gvCOUNpXsWrIQ3A4aXCLIdblL0tDq42BG/2Xw7oxbil9h11uow10ztS2GuFazNBfjbrsZ5nl+nPl5jDSjj5TSg== dependencies: ajv "^6.12.6" -"@hapi/bourne@^2.0.0": +"@fastify/busboy@^1.0.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@fastify/busboy/-/busboy-1.1.0.tgz" + integrity sha512-Fv854f94v0CzIDllbY3i/0NJPNBRNLDawf3BTYVGCe9VrIIs3Wi7AFx24F9NzCxdf0wyx/x0Q9kEVnvDOPnlxA== + dependencies: + text-decoding "^1.0.0" + +"@fastify/caching@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@fastify/caching/-/caching-7.0.0.tgz#8e142fb88f4e6f3f873e6d190e18c4df32cff1ec" + integrity sha512-zMZzUmtByWKeqW8WMt0PILgGIUHLopSGjVPK2pDSPhcrdf9/B/gA4FiW4ylJVY0fhkW18awqI3z+tgUiY6mPsw== + dependencies: + abstract-cache "^1.0.1" + fastify-plugin "^3.0.1" + uid-safe "^2.1.5" + +"@fastify/error@^2.0.0": version "2.0.0" - resolved "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.0.0.tgz" - integrity sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg== + resolved "https://registry.npmjs.org/@fastify/error/-/error-2.0.0.tgz" + integrity sha512-wI3fpfDT0t7p8E6dA2eTECzzOd+bZsZCJ2Hcv+Onn2b7ZwK3RwD27uW2QDaMtQhAfWQQP+WNK7nKf0twLsBf9w== + +"@fastify/formbody@^6.0.0": + version "6.0.1" + resolved "https://registry.npmjs.org/@fastify/formbody/-/formbody-6.0.1.tgz" + integrity sha512-yIwCitoES4Sh0tPc6v+uHBqZEKw3CooSZ4kUvO9NC8Y7oRBCW+aC+pTgUZ8M3r2DOzRkNO+Pq0jMQkyL2k8jZQ== + dependencies: + fastify-plugin "^3.0.0" + +"@fastify/static@^5.0.1": + version "5.0.2" + resolved "https://registry.npmjs.org/@fastify/static/-/static-5.0.2.tgz" + integrity sha512-HvyXZ5a7hUHoSBRq9jKUuKIUCkHMkCDcmiAeEmixXlGOx8pEWx3NYOIaiivcjWa6/NLvfdUT+t/jzfVQ2PA7Gw== + dependencies: + content-disposition "^0.5.3" + encoding-negotiator "^2.0.1" + fastify-plugin "^3.0.0" + glob "^7.1.4" + p-limit "^3.1.0" + readable-stream "^3.4.0" + send "^0.17.1" + +"@ffprobe-installer/darwin-arm64@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/darwin-arm64/-/darwin-arm64-5.0.1.tgz#a020a623955d55aa8daf45cb668c3044876b553b" + integrity sha512-vwNCNjokH8hfkbl6m95zICHwkSzhEvDC3GVBcUp5HX8+4wsX10SP3B+bGur7XUzTIZ4cQpgJmEIAx6TUwRepMg== + +"@ffprobe-installer/darwin-x64@5.0.0": + version "5.0.0" + resolved "https://registry.npmjs.org/@ffprobe-installer/darwin-x64/-/darwin-x64-5.0.0.tgz" + integrity sha512-Zl0UkZ+wW/eyMKBPLTUCcNQch2VDnZz/cBn1DXv3YtCBVbYd9aYzGj4MImdxgWcoE0+GpbfbO6mKGwMq5HCm6A== + +"@ffprobe-installer/ffprobe@^1.4.1": + version "1.4.1" + resolved "https://registry.npmjs.org/@ffprobe-installer/ffprobe/-/ffprobe-1.4.1.tgz" + integrity sha512-3WJvxU0f4d7IOZdzoVCAj9fYtiQNC6E0521FJFe9iP5Ej8auTXU7TsrUzIAG1CydeQI+BnM3vGog92SCcF9KtA== + optionalDependencies: + "@ffprobe-installer/darwin-arm64" "5.0.1" + "@ffprobe-installer/darwin-x64" "5.0.0" + "@ffprobe-installer/linux-arm" "5.0.0" + "@ffprobe-installer/linux-arm64" "5.0.0" + "@ffprobe-installer/linux-ia32" "5.0.0" + "@ffprobe-installer/linux-x64" "5.0.0" + "@ffprobe-installer/win32-ia32" "5.0.0" + "@ffprobe-installer/win32-x64" "5.0.0" + +"@ffprobe-installer/linux-arm64@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/linux-arm64/-/linux-arm64-5.0.0.tgz#8e50c2ac0fa9f1ccaf553114c09cc9d2f9571de2" + integrity sha512-IwFbzhe1UydR849YXLPP0RMpHgHXSuPO1kznaCHcU5FscFBV5gOZLkdD8e/xrcC8g/nhKqy0xMjn5kv6KkFQlQ== + +"@ffprobe-installer/linux-arm@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/linux-arm/-/linux-arm-5.0.0.tgz#0a67b1610284e4be115da1656f150abc4706fe08" + integrity sha512-mM1PPxP2UX5SUvhy0urcj5U8UolwbYgmnXA/eBWbW78k6N2Wk1COvcHYzOPs6c5yXXL6oshS2rZHU1kowigw7g== + +"@ffprobe-installer/linux-ia32@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/linux-ia32/-/linux-ia32-5.0.0.tgz#38714de93ce3842887e51a8b0c9dab3297777dbb" + integrity sha512-c3bWlWEDMST59SAZycVh0oyc2eNS/CxxeRjoNryGRgqcZX3EJWJJQL1rAXbpQOMLMi8to1RqnmMuwPJgLLjjUA== + +"@ffprobe-installer/linux-x64@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/linux-x64/-/linux-x64-5.0.0.tgz#dc51a99acf74675035c02f59c4d73270ba3742f7" + integrity sha512-zgLnWJFvMGCaw1txGtz84sMEQt6mQUzdw86ih9S/kZOWnp06Gj/ams/EXxEkAxgAACCVM6/O0mkDe/6biY5tgA== + +"@ffprobe-installer/win32-ia32@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/win32-ia32/-/win32-ia32-5.0.0.tgz#77f5cfba1aa91e47255562d23a07432b3e087bb1" + integrity sha512-NnDdAZD6ShFXzJeCkAFl2ZjAv7GcJWYudLA+0T/vjZwvskBop+sq1PGfdmVltfFDcdQiomoThRhn9Xiy9ZC71g== + +"@ffprobe-installer/win32-x64@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@ffprobe-installer/win32-x64/-/win32-x64-5.0.0.tgz#8ed741260b7db346c7bfe77d2fd9acbe3bd70d2f" + integrity sha512-P4ZMRFxVMnfMsOyTfBM/+nkTodLeOUfXNPo+X1bKEWBiZxRErqX/IHS5sLA0yAH8XmtKZcL7Cu6M26ztGcQYxw== + +"@hapi/bourne@^2.0.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@hapi/bourne/-/bourne-2.1.0.tgz" + integrity sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q== "@humanwhocodes/config-array@^0.5.0": version "0.5.0" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== dependencies: "@humanwhocodes/object-schema" "^1.2.0" @@ -990,13 +1194,13 @@ minimatch "^3.0.4" "@humanwhocodes/object-schema@^1.2.0": - version "1.2.0" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz" - integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + version "1.2.1" + resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" + 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" @@ -1007,12 +1211,12 @@ "@istanbuljs/schema@^0.1.2": version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== "@jest/console@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== dependencies: "@jest/types" "^26.6.2" @@ -1024,7 +1228,7 @@ "@jest/core@^26.6.3": version "26.6.3" - resolved "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== dependencies: "@jest/console" "^26.6.2" @@ -1058,7 +1262,7 @@ "@jest/environment@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== dependencies: "@jest/fake-timers" "^26.6.2" @@ -1068,7 +1272,7 @@ "@jest/fake-timers@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== dependencies: "@jest/types" "^26.6.2" @@ -1080,7 +1284,7 @@ "@jest/globals@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== dependencies: "@jest/environment" "^26.6.2" @@ -1089,7 +1293,7 @@ "@jest/reporters@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== dependencies: "@bcoe/v8-coverage" "^0.2.3" @@ -1121,7 +1325,7 @@ "@jest/source-map@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== dependencies: callsites "^3.0.0" @@ -1130,7 +1334,7 @@ "@jest/test-result@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== dependencies: "@jest/console" "^26.6.2" @@ -1140,7 +1344,7 @@ "@jest/test-sequencer@^26.6.3": version "26.6.3" - resolved "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== dependencies: "@jest/test-result" "^26.6.2" @@ -1151,7 +1355,7 @@ "@jest/transform@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== dependencies: "@babel/core" "^7.1.0" @@ -1172,7 +1376,7 @@ "@jest/types@^26.6.2": version "26.6.2" - resolved "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" @@ -1181,24 +1385,64 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.0.3": + version "3.0.8" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.8.tgz" + integrity sha512-YK5G9LaddzGbcucK4c8h5tWFmMPBvRZ/uyWmN1/SbBdIvqGUdWGkJ5BAaccgs6XbzVLsqbPJrBSFwKv3kT9i7w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.9": + version "0.3.14" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz" + integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@mapbox/node-pre-gyp@^1.0.0": - version "1.0.5" - resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz" - integrity sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA== + version "1.0.9" + resolved "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz" + integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw== dependencies: - detect-libc "^1.0.3" + detect-libc "^2.0.0" https-proxy-agent "^5.0.0" make-dir "^3.1.0" - node-fetch "^2.6.1" + node-fetch "^2.6.7" nopt "^5.0.0" - npmlog "^4.1.2" + npmlog "^5.0.1" rimraf "^3.0.2" - semver "^7.3.4" - tar "^6.1.0" + semver "^7.3.5" + tar "^6.1.11" "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -1206,148 +1450,204 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@redis/bloom@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@redis/bloom/-/bloom-1.0.2.tgz#42b82ec399a92db05e29fffcdfd9235a5fc15cdf" + integrity sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw== + +"@redis/client@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@redis/client/-/client-1.2.0.tgz#be2ef974881e57276123cb76d08756c03eed946f" + integrity sha512-a8Nlw5fv2EIAFJxTDSSDVUT7yfBGpZO96ybZXzQpgkyLg/dxtQ1uiwTc0EGfzg1mrPjZokeBSEGTbGXekqTNOg== + dependencies: + cluster-key-slot "1.1.0" + generic-pool "3.8.2" + yallist "4.0.0" + +"@redis/graph@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@redis/graph/-/graph-1.0.1.tgz#eabc58ba99cd70d0c907169c02b55497e4ec8a99" + integrity sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ== + +"@redis/json@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@redis/json/-/json-1.0.3.tgz#a13fde1d22ebff0ae2805cd8e1e70522b08ea866" + integrity sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q== + +"@redis/search@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@redis/search/-/search-1.0.6.tgz#53d7451c2783f011ebc48ec4c2891264e0b22f10" + integrity sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA== + +"@redis/time-series@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@redis/time-series/-/time-series-1.0.3.tgz#4cfca8e564228c0bddcdf4418cba60c20b224ac4" + integrity sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA== + "@segment/loosely-validate-event@^2.0.0": version "2.0.0" - resolved "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681" integrity sha512-ZMCSfztDBqwotkl848ODgVcAmN4OItEWDCkshcKz0/W6gGSQayuuCtWV/MlodFivAZD793d6UgANd6wCXUfrIw== dependencies: component-type "^1.2.1" join-component "^1.1.0" -"@sentry/core@6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/core/-/core-6.13.3.tgz" - integrity sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA== +"@selderee/plugin-htmlparser2@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz#27e994afd1c2cb647ceb5406a185a5574188069d" + integrity sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA== + dependencies: + domhandler "^4.2.0" + selderee "^0.6.0" + +"@sentry/core@6.19.7": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/core/-/core-6.19.7.tgz" + integrity sha512-tOfZ/umqB2AcHPGbIrsFLcvApdTm9ggpi/kQZFkej7kMphjT+SGBiQfYtjyg9jcRW+ilAR4JXC9BGKsdEQ+8Vw== dependencies: - "@sentry/hub" "6.13.3" - "@sentry/minimal" "6.13.3" - "@sentry/types" "6.13.3" - "@sentry/utils" "6.13.3" + "@sentry/hub" "6.19.7" + "@sentry/minimal" "6.19.7" + "@sentry/types" "6.19.7" + "@sentry/utils" "6.19.7" tslib "^1.9.3" -"@sentry/hub@6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/hub/-/hub-6.13.3.tgz" - integrity sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw== +"@sentry/hub@6.19.7": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz" + integrity sha512-y3OtbYFAqKHCWezF0EGGr5lcyI2KbaXW2Ik7Xp8Mu9TxbSTuwTe4rTntwg8ngPjUQU3SUHzgjqVB8qjiGqFXCA== dependencies: - "@sentry/types" "6.13.3" - "@sentry/utils" "6.13.3" + "@sentry/types" "6.19.7" + "@sentry/utils" "6.19.7" tslib "^1.9.3" -"@sentry/minimal@6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.13.3.tgz" - integrity sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw== +"@sentry/minimal@6.19.7": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/minimal/-/minimal-6.19.7.tgz" + integrity sha512-wcYmSJOdvk6VAPx8IcmZgN08XTXRwRtB1aOLZm+MVHjIZIhHoBGZJYTVQS/BWjldsamj2cX3YGbGXNunaCfYJQ== dependencies: - "@sentry/hub" "6.13.3" - "@sentry/types" "6.13.3" + "@sentry/hub" "6.19.7" + "@sentry/types" "6.19.7" tslib "^1.9.3" -"@sentry/node@^6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/node/-/node-6.13.3.tgz" - integrity sha512-ZeZSw+TcPcf4e0j7iEqNMtoVmz+WFW/TEoGokXIwysZqSgchKdAXDHqn+CqUqFan7d76JcJmzztAUK2JruQ2Kg== +"@sentry/node@^6.15.0": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/node/-/node-6.19.7.tgz" + integrity sha512-gtmRC4dAXKODMpHXKfrkfvyBL3cI8y64vEi3fDD046uqYcrWdgoQsffuBbxMAizc6Ez1ia+f0Flue6p15Qaltg== dependencies: - "@sentry/core" "6.13.3" - "@sentry/hub" "6.13.3" - "@sentry/tracing" "6.13.3" - "@sentry/types" "6.13.3" - "@sentry/utils" "6.13.3" + "@sentry/core" "6.19.7" + "@sentry/hub" "6.19.7" + "@sentry/types" "6.19.7" + "@sentry/utils" "6.19.7" cookie "^0.4.1" https-proxy-agent "^5.0.0" lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/tracing@6.13.3", "@sentry/tracing@^6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.13.3.tgz" - integrity sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q== +"@sentry/tracing@^6.15.0": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/tracing/-/tracing-6.19.7.tgz" + integrity sha512-ol4TupNnv9Zd+bZei7B6Ygnr9N3Gp1PUrNI761QSlHtPC25xXC5ssSD3GMhBgyQrcvpuRcCFHVNNM97tN5cZiA== dependencies: - "@sentry/hub" "6.13.3" - "@sentry/minimal" "6.13.3" - "@sentry/types" "6.13.3" - "@sentry/utils" "6.13.3" + "@sentry/hub" "6.19.7" + "@sentry/minimal" "6.19.7" + "@sentry/types" "6.19.7" + "@sentry/utils" "6.19.7" tslib "^1.9.3" -"@sentry/types@6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/types/-/types-6.13.3.tgz" - integrity sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A== +"@sentry/types@6.19.7": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/types/-/types-6.19.7.tgz" + integrity sha512-jH84pDYE+hHIbVnab3Hr+ZXr1v8QABfhx39KknxqKWr2l0oEItzepV0URvbEhB446lk/S/59230dlUUIBGsXbg== -"@sentry/utils@6.13.3": - version "6.13.3" - resolved "https://registry.npmjs.org/@sentry/utils/-/utils-6.13.3.tgz" - integrity sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag== +"@sentry/utils@6.19.7": + version "6.19.7" + resolved "https://registry.npmjs.org/@sentry/utils/-/utils-6.19.7.tgz" + integrity sha512-z95ECmE3i9pbWoXQrD/7PgkBAzJYR+iXtPuTkpBjDKs86O3mT+PXOT3BAn79w2wkn7/i3vOGD2xVr1uiMl26dA== dependencies: - "@sentry/types" "6.13.3" + "@sentry/types" "6.19.7" tslib "^1.9.3" "@sindresorhus/is@^0.14.0": version "0.14.0" - resolved "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sinonjs/commons@^1.7.0": version "1.8.3" - resolved "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== dependencies: type-detect "4.0.8" "@sinonjs/fake-timers@^6.0.1": version "6.0.1" - resolved "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== dependencies: "@sinonjs/commons" "^1.7.0" +"@socket.io/component-emitter@~3.1.0": + version "3.1.0" + resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz" + integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== + +"@socket.io/redis-adapter@^7.1.0": + version "7.2.0" + resolved "https://registry.npmjs.org/@socket.io/redis-adapter/-/redis-adapter-7.2.0.tgz" + integrity sha512-/r6oF6Myz0K9uatB/pfCi0BhKg/KRMh1OokrqcjlNz6aq40WiXdFLRbHJQuwGHq/KvB+D6141K+IynbVxZGvhw== + dependencies: + debug "~4.3.1" + notepack.io "~2.2.0" + socket.io-adapter "^2.4.0" + uid2 "0.0.3" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== dependencies: defer-to-connect "^1.0.1" "@tootallnate/once@1": version "1.1.2" - resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== "@types/amqp-connection-manager@^2.0.10": version "2.0.12" - resolved "https://registry.npmjs.org/@types/amqp-connection-manager/-/amqp-connection-manager-2.0.12.tgz" + resolved "https://registry.yarnpkg.com/@types/amqp-connection-manager/-/amqp-connection-manager-2.0.12.tgz#809a01207193ffc15b1689806b51dfeba7b3f9f3" integrity sha512-2GX1jG6ECpEXQF0X68gTTZc8MQ8GA0dM2mAd1irTpWlKzGKlGzCBtb1YnqLHozNNsoLtGI6UXSp0q06jU1LA6g== dependencies: "@types/amqplib" "*" "@types/amqplib@*": version "0.8.2" - resolved "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.2.tgz" + resolved "https://registry.yarnpkg.com/@types/amqplib/-/amqplib-0.8.2.tgz#9c46f2c7fac381e4f81bcb612c00d54549697d22" integrity sha512-p+TFLzo52f8UanB+Nq6gyUi65yecAcRY3nYowU6MPGFtaJvEDxcnFWrxssSTkF+ts1W3zyQDvgVICLQem5WxRA== dependencies: "@types/bluebird" "*" "@types/node" "*" "@types/analytics-node@^3.1.5": - version "3.1.5" - resolved "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.5.tgz" - integrity sha512-zSqNpyzF3hcweslf7ttqB03iZvxtymUh820SAXaFhox5Y5Qa7bYmrdOi4IW050OHrKmtq4SE4kE1XeE1mK+zrQ== + version "3.1.9" + resolved "https://registry.npmjs.org/@types/analytics-node/-/analytics-node-3.1.9.tgz" + integrity sha512-C7L7/Dd/CmBST7AvgoCnf4yI9h6W5aYfCOcfUZS5GHlXDQjnXLVOUDpTdwTIZjW4lKECeil6+G+Ul6Xzwv/P0g== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": - version "7.1.15" - resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz" - integrity sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew== + version "7.1.19" + resolved "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz" + integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1356,177 +1656,211 @@ "@types/babel__traverse" "*" "@types/babel__generator@*": - version "7.6.3" - resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz" - integrity sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA== + version "7.6.4" + resolved "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz" + integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg== dependencies: "@babel/types" "^7.0.0" "@types/babel__template@*": version "7.4.1" - resolved "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969" integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": - version "7.14.2" - resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz" - integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + version "7.17.1" + resolved "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz" + integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== dependencies: "@babel/types" "^7.3.0" "@types/bcrypt@^5.0.0": version "5.0.0" - resolved "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.0.tgz#a835afa2882d165aff5690893db314eaa98b9f20" integrity sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw== dependencies: "@types/node" "*" "@types/bluebird@*": version "3.5.36" - resolved "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652" integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q== "@types/busboy@^0.2.3": version "0.2.4" - resolved "https://registry.npmjs.org/@types/busboy/-/busboy-0.2.4.tgz" + resolved "https://registry.yarnpkg.com/@types/busboy/-/busboy-0.2.4.tgz#19922f8c7076ad6d47b2565da8c0a94c88776315" integrity sha512-f+ZCVjlcN8JW/zf3iR0GqO4gjOUlltMTtZjn+YR1mlK+MVu6esTiIecO0/GQlmYQPQLdBnc7+5vG3Xb+SkvFLw== dependencies: "@types/node" "*" "@types/chai@^4.2.12": - version "4.2.21" - resolved "https://registry.npmjs.org/@types/chai/-/chai-4.2.21.tgz" - integrity sha512-yd+9qKmJxm496BOV9CMNaey8TWsikaZOwMRwPHQIjcOJM9oV+fi9ZMNw3JsVnbEEbo2gRTDnGEBv8pjyn67hNg== + version "4.3.1" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.3.1.tgz" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== "@types/cli-table@^0.3.0": version "0.3.0" - resolved "https://registry.npmjs.org/@types/cli-table/-/cli-table-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/@types/cli-table/-/cli-table-0.3.0.tgz#f1857156bf5fd115c6a2db260ba0be1f8fc5671c" integrity sha512-QnZUISJJXyhyD6L1e5QwXDV/A5i2W1/gl6D6YMc8u0ncPepbv/B4w3S+izVvtAg60m6h+JP09+Y/0zF2mojlFQ== "@types/component-emitter@^1.2.10": - version "1.2.10" - resolved "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz" - integrity sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg== + version "1.2.11" + resolved "https://registry.yarnpkg.com/@types/component-emitter/-/component-emitter-1.2.11.tgz#50d47d42b347253817a39709fef03ce66a108506" + integrity sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ== "@types/config@0.0.36": version "0.0.36" - resolved "https://registry.npmjs.org/@types/config/-/config-0.0.36.tgz" + resolved "https://registry.yarnpkg.com/@types/config/-/config-0.0.36.tgz#bf53ca640f3a1a6a2072a9f33e02a44def07a40b" integrity sha512-EoAeT1MyFWh2BJvBDEFInY714bQBbHOAucqxqqhprhbBFqr+B7fuN5T9CJqUIGDzvwubnKKRqmSo6yPo0aSpNw== +"@types/cookie@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" + integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== + "@types/cookiejar@*": version "2.1.2" - resolved "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== -"@types/engine.io@*": - version "3.1.7" - resolved "https://registry.npmjs.org/@types/engine.io/-/engine.io-3.1.7.tgz" - integrity sha512-qNjVXcrp+1sS8YpRUa714r0pgzOwESdW5UjHL7D/2ZFdBX0BXUXtg1LUrp+ylvqbvMcMWUy73YpRoxPN2VoKAQ== - dependencies: - "@types/node" "*" +"@types/cors@^2.8.12": + version "2.8.12" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" + integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== "@types/eslint@^7.2.3": - version "7.28.0" - resolved "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.0.tgz" - integrity sha512-07XlgzX0YJUn4iG1ocY4IX9DzKSmMGUs6ESKlxWhZRaa0fatIWaHWUVapcuGa8r5HFnTqzj+4OCjd5f7EZ/i/A== + version "7.29.0" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-7.29.0.tgz" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== dependencies: "@types/estree" "*" "@types/json-schema" "*" "@types/estree@*": - version "0.0.50" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== + version "0.0.52" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.52.tgz" + integrity sha512-BZWrtCU0bMVAIliIV+HJO1f1PR41M7NKjfxrFJwwhKI1KwhwOxYw1SXg9ao+CIMt774nFuGiG6eU+udtbEI9oQ== "@types/fastify-multipart@^0.7.0": version "0.7.0" - resolved "https://registry.npmjs.org/@types/fastify-multipart/-/fastify-multipart-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/@types/fastify-multipart/-/fastify-multipart-0.7.0.tgz#fcbabfb35e69af0290a1c6c83199fc7e03855a51" integrity sha512-dKK9S8nBesXhSfUlgyGE7mNJ5a1TxiBeIalJFdPbUj5bJywgjo3ixpm+LcIpTK2UwQ10OWptny/Kjc3GprREtg== dependencies: fastify-multipart "*" +"@types/fastify-static@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@types/fastify-static/-/fastify-static-2.2.1.tgz#7e8f7e87d894bc5bf4bb8eef8a13229290aaa622" + integrity sha512-jDE4J3nkhmBbDwopkaEmJzbGnCc1YWlkCeKPtdh9B6SuPH3RJv8SMf1Tv3nGel/RL2GUWN3tkhhFVJogqrmtMw== + dependencies: + fastify-static "*" + +"@types/fluent-ffmpeg@^2.1.20": + version "2.1.20" + resolved "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.20.tgz" + integrity sha512-B+OvhCdJ3LgEq2PhvWNOiB/EfwnXLElfMCgc4Z1K5zXgSfo9I6uGKwR/lqmNPFQuebNnes7re3gqkV77SyypLg== + dependencies: + "@types/node" "*" + "@types/graceful-fs@^4.1.2": version "4.1.5" - resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== dependencies: "@types/node" "*" +"@types/html-to-text@^8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@types/html-to-text/-/html-to-text-8.1.1.tgz#0c5573207c14f618f24da5a2910c510285573094" + integrity sha512-QFcqfc7TiVbvIX8Fc2kWUxakruI1Ay6uitaGCYHzI5M0WHQROV5D2XeSaVrK0FmvssivXum4yERVnJsiuH61Ww== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.3" - resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz" - integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + version "2.0.4" + resolved "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== "@types/istanbul-lib-report@*": version "3.0.0" - resolved "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": version "3.0.1" - resolved "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== dependencies: "@types/istanbul-lib-report" "*" "@types/jest@^26.0.14": version "26.0.24" - resolved "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.24.tgz#943d11976b16739185913a1936e0de0c4a7d595a" integrity sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w== dependencies: jest-diff "^26.0.0" pretty-format "^26.0.0" "@types/json-schema@*", "@types/json-schema@^7.0.7": - version "7.0.9" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== + version "7.0.11" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/jsonwebtoken@^8.5.0": - version "8.5.5" - resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.5.tgz" - integrity sha512-OGqtHQ7N5/Ap/TUwO6IgHDuLiAoTmHhGpNvgkCm/F4N6pKzx/RBSfr2OXZSwC6vkfnsEdb6+7DNZVtiXiwdwFw== + version "8.5.8" + resolved "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.8.tgz" + integrity sha512-zm6xBQpFDIDM6o9r6HSgDeIcLy82TKWctCXEPbJJcXb5AKmi5BNNdLXneixK4lplX3PqIVcwLBCGE/kAGnlD4A== dependencies: "@types/node" "*" "@types/lodash@^4.14.165": - version "4.14.172" - resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.172.tgz" - integrity sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw== + version "4.14.182" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== "@types/long@^4.0.0": - version "4.0.1" - resolved "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz" - integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== + version "4.0.2" + resolved "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz" + integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== + +"@types/minimist@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== "@types/minio@^7.0.7": - version "7.0.9" - resolved "https://registry.npmjs.org/@types/minio/-/minio-7.0.9.tgz" - integrity sha512-aMalbSDDB+TV9m3fVMD4E2vJR3XVAtOcf9t5Iq+PHnc5D0ti3LMXjaxGKXmllicliaBrh0gzURLrs44n/Jl43g== + version "7.0.13" + resolved "https://registry.npmjs.org/@types/minio/-/minio-7.0.13.tgz" + integrity sha512-Warrx6uN4KEpBCAWiTh7ngrPoaNIckawtBXqWbFzaatG/NPRZToAv/fa9yAPA7a2FHAGhe154KqaVIqacIn2pQ== dependencies: "@types/node" "*" "@types/mongodb@^4.0.7": version "4.0.7" - resolved "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz" + resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-4.0.7.tgz#ebaa80c53b684ea52ccfe7721c0f5c9ef7b4f511" integrity sha512-lPUYPpzA43baXqnd36cZ9xxorprybxXDzteVKCPAdp14ppHtFJHnXYvNpmBvtMUTb5fKXVv6sVbzo1LHkWhJlw== dependencies: mongodb "*" +"@types/needle@*": + version "2.5.3" + resolved "https://registry.npmjs.org/@types/needle/-/needle-2.5.3.tgz" + integrity sha512-RwgTwMRaedfyCBe5SSWMpm1Yqzc5UPZEMw0eAd09OSyV93nLRj9/evMGZmgFeHKzUOd4xxtHvgtc+rjcBjI1Qg== + dependencies: + "@types/node" "*" + "@types/node-cron@^3.0.0": - version "3.0.0" - resolved "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.0.tgz" - integrity sha512-RNBIyVwa/1v2r8/SqK8tadH2sJlFRAo5Ghac/cOcCv4Kp94m0I03UmAh9WVhCqS9ZdB84dF3x47p9aTw8E4c4A== + version "3.0.2" + resolved "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.2.tgz" + integrity sha512-SK/4GYWiWvGLPl/yv+Tm5oLYbzMx1V3y7CsNTvOb3vF8O9oXH11U6/zckISHnBl4YH8MvXHFIUXbYoBONSdmzw== -"@types/node-fetch@^2.5.10": - version "2.5.12" - resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz" - integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== +"@types/node-fetch@^2.5.12": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== dependencies: "@types/node" "*" form-data "^3.0.0" @@ -1534,43 +1868,44 @@ "@types/node-uuid@^0.0.28": version "0.0.28" resolved "https://registry.npmjs.org/@types/node-uuid/-/node-uuid-0.0.28.tgz" - integrity sha1-QWVbXOY7LzN0xOgmtN0h5ykFjj0= + integrity sha512-FOZsQldDy39ox+grtoZfGC43zLz88fBZo+YbH+ROXqrHw2stPSnOL5nMTrq4I2q+Kd8rBU2PEXMN/HO9nIrvQQ== dependencies: "@types/node" "*" -"@types/node@*", "@types/node@>=8", "@types/node@^14.11.2": - version "14.17.11" - resolved "https://registry.npmjs.org/@types/node/-/node-14.17.11.tgz" - integrity sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w== +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=8", "@types/node@^14.0.1", "@types/node@^14.11.2": + version "14.18.21" + resolved "https://registry.npmjs.org/@types/node/-/node-14.18.21.tgz" + integrity sha512-x5W9s+8P4XteaxT/jKF0PSb7XEvo5VmqEWgsMlyeY4ZlLK8I6aH6g5TPPyDlLAep+GYf4kefb7HFyc7PAO3m+Q== "@types/normalize-package-data@^2.4.0": version "2.4.1" - resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== "@types/pdf-image@^2.0.1": version "2.0.1" - resolved "https://registry.npmjs.org/@types/pdf-image/-/pdf-image-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/@types/pdf-image/-/pdf-image-2.0.1.tgz#c05af33ba65d70e9dad2da99b33c9c027d0686f7" integrity sha512-WSG+F90yd53I2iA3/MiRolRmP0hT0GLkfdq2CYg1sW1AmsWK9bitc9v0EaakkMvFebESzoU/P4vsUhYnDz/OYw== "@types/pino-pretty@*": - version "4.7.1" - resolved "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-4.7.1.tgz" - integrity sha512-l1ntNXdpVWsnPYUk5HyO5Lxfr38zLCgxVfEn/9Zhhm+nGF04/BiIou/m8XPwvoVZLV+livUo79VdHXMJPfUYxA== + version "4.7.5" + resolved "https://registry.npmjs.org/@types/pino-pretty/-/pino-pretty-4.7.5.tgz" + integrity sha512-rfHe6VIknk14DymxGqc9maGsRe8/HQSvM2u46EAz2XrS92qsAJnW16dpdFejBuZKD8cRJX6Aw6uVZqIQctMpAg== dependencies: - "@types/pino" "*" + "@types/node" "*" + "@types/pino" "6.3" "@types/pino-std-serializers@*": version "2.4.1" - resolved "https://registry.npmjs.org/@types/pino-std-serializers/-/pino-std-serializers-2.4.1.tgz" + resolved "https://registry.yarnpkg.com/@types/pino-std-serializers/-/pino-std-serializers-2.4.1.tgz#f8bd52a209c8b3c97d1533b1ba27f57c816382bf" integrity sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ== dependencies: "@types/node" "*" -"@types/pino@*", "@types/pino@^6.3.2": - version "6.3.11" - resolved "https://registry.npmjs.org/@types/pino/-/pino-6.3.11.tgz" - integrity sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ== +"@types/pino@6.3", "@types/pino@^6.3.2": + version "6.3.12" + resolved "https://registry.npmjs.org/@types/pino/-/pino-6.3.12.tgz" + integrity sha512-dsLRTq8/4UtVSpJgl9aeqHvbh6pzdmjYD3C092SYgLD2TyoCqHpTJk6vp8DvCTGGc7iowZ2MoiYiVUUCcu7muw== dependencies: "@types/node" "*" "@types/pino-pretty" "*" @@ -1578,220 +1913,233 @@ sonic-boom "^2.1.0" "@types/prettier@^2.0.0": - version "2.3.2" - resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.2.tgz" - integrity sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog== + version "2.6.3" + resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz" + integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== -"@types/redis@*": - version "2.8.31" - resolved "https://registry.npmjs.org/@types/redis/-/redis-2.8.31.tgz" - integrity sha512-daWrrTDYaa5iSDFbgzZ9gOOzyp2AJmYK59OlG/2KGBgYWF3lfs8GDKm1c//tik5Uc93hDD36O+qLPvzDolChbA== +"@types/probe-image-size@^7.0.1": + version "7.2.0" + resolved "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.0.tgz" + integrity sha512-R5H3vw62gHNHrn+JGZbKejb+Z2D/6E5UNVlhCzIaBBLroMQMOFqy5Pap2gM+ZZHdqBtVU0/cx/M6to+mOJcoew== dependencies: + "@types/needle" "*" "@types/node" "*" -"@types/sharp@^0.28.5": - version "0.28.6" - resolved "https://registry.npmjs.org/@types/sharp/-/sharp-0.28.6.tgz" - integrity sha512-AjKjo5vk5mkcTrWL0U1zFUdCp/uqLebvbe7ezAJx0tgp6ST9JmfsYK1q1lpjfPM5S1YQ1wr5uboPSu2S8UO9yw== +"@types/pump@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/pump/-/pump-1.1.1.tgz#edb3475e2bad0f4552bdaa91c6c43b82e08ff15e" + integrity sha512-wpRerjHDxFBQ4r8XNv3xHJZeuqrBBoeQ/fhgkooV2F7KsPIYRROb/+f9ODgZfOEyO5/w2ej4YQdpPPXipT8DAA== + dependencies: + "@types/node" "*" + +"@types/random-useragent@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@types/random-useragent/-/random-useragent-0.3.1.tgz#1f0e1e08151f04d2c023ab77c8173dfa5b5049d2" + integrity sha512-yVz7897JjjwS6V+lmxlu8pktzNnNWgtF9MGxfaRfI8o+hQageO9K+0hfwr8PspdFJIIRE9KkLqp4o5tlQqv/0w== + +"@types/redis@^4.0.11": + version "4.0.11" + resolved "https://registry.yarnpkg.com/@types/redis/-/redis-4.0.11.tgz#0bb4c11ac9900a21ad40d2a6768ec6aaf651c0e1" + integrity sha512-bI+gth8La8Wg/QCR1+V1fhrL9+LZUSWfcqpOj2Kc80ZQ4ffbdL173vQd5wovmoV9i071FU9oP2g6etLuEwb6Rg== + dependencies: + redis "*" + +"@types/sharp@^0.29.5": + version "0.29.5" + resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.29.5.tgz#9c7032d30d138ad16dde6326beaff2af757b91b3" + integrity sha512-3TC+S3H5RwnJmLYMHrcdfNjz/CaApKmujjY9b6PU/pE6n0qfooi99YqXGWoW8frU9EWYj/XTI35Pzxa+ThAZ5Q== dependencies: "@types/node" "*" "@types/socket.io-client@^1.4.34": version "1.4.36" - resolved "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz" + resolved "https://registry.yarnpkg.com/@types/socket.io-client/-/socket.io-client-1.4.36.tgz#e4f1ca065f84c20939e9850e70222202bd76ff3f" integrity sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag== -"@types/socket.io-parser@*": +"@types/socket.io-parser@^3.0.0": version "3.0.0" - resolved "https://registry.npmjs.org/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/@types/socket.io-parser/-/socket.io-parser-3.0.0.tgz#9726d3ab9235757a0a30dd5ccf8975dce54e5e2c" integrity sha512-Ry/rbTE6HQNL9eu3LpL1Ocup5VexXu1bSSGlSho/IR5LuRc8YvxwSNJ3JxqTltVJEATLbZkMQETSbxfKNgp4Ew== dependencies: socket.io-parser "*" -"@types/socket.io-redis@^1.0.26": - version "1.0.27" - resolved "https://registry.npmjs.org/@types/socket.io-redis/-/socket.io-redis-1.0.27.tgz" - integrity sha512-oyJPDjn5Dnci3wZD2bd1jfPsJkqvTwoNGpOIF+/+P45cOn4zrYsUO9mcGN/shoxIlCz6bcdRhSRXWwZFGQc1PA== - dependencies: - "@types/redis" "*" - "@types/socket.io" "*" - -"@types/socket.io@*", "@types/socket.io@^2.1.11": - version "2.1.13" - resolved "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz" - integrity sha512-JRgH3nCgsWel4OPANkhH8TelpXvacAJ9VeryjuqCDiaVDMpLysd6sbt0dr6Z15pqH3p2YpOT3T1C5vQ+O/7uyg== - dependencies: - "@types/engine.io" "*" - "@types/node" "*" - "@types/socket.io-parser" "*" - "@types/stack-utils@^2.0.0": version "2.0.1" - resolved "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/strip-bom@^3.0.0": version "3.0.0" resolved "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz" - integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I= + integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== "@types/strip-json-comments@0.0.30": version "0.0.30" - resolved "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz" + resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== "@types/superagent@*": - version "4.1.12" - resolved "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.12.tgz" - integrity sha512-1GQvD6sySQPD6p9EopDFI3f5OogdICl1sU/2ij3Esobz/RtL9fWZZDPmsuv7eiy5ya+XNiPAxUcI3HIUTJa+3A== + version "4.1.15" + resolved "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.15.tgz" + integrity sha512-mu/N4uvfDN2zVQQ5AYJI/g4qxn2bHB6521t1UuH09ShNWjebTqN0ZFuYK9uYjcgmI0dTQEs+Owi1EO6U0OkOZQ== dependencies: "@types/cookiejar" "*" "@types/node" "*" "@types/supertest@2.0.4": version "2.0.4" - resolved "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.4.tgz#28770e13293365e240a842d7d5c5a1b3d2dee593" integrity sha512-0TvOJ+6XVMSImgqc2ClNllfVffCxHQhFbsbwOGzGTjdFydoaG052LPqnP8SnmSlnokOcQiPPcbz+Yi30LxWPyA== dependencies: "@types/superagent" "*" "@types/uuid@^8.3.0": - version "8.3.1" - resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz" - integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg== + version "8.3.4" + resolved "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz" + integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== "@types/webidl-conversions@*": version "6.1.1" - resolved "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz" + resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz#e33bc8ea812a01f63f90481c666334844b12a09e" integrity sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q== -"@types/whatwg-url@^8.0.0": - version "8.2.1" - resolved "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz" - integrity sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ== +"@types/whatwg-url@^8.2.1": + version "8.2.2" + resolved "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz" + integrity sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA== dependencies: "@types/node" "*" "@types/webidl-conversions" "*" "@types/ws@^7.2.7": version "7.4.7" - resolved "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== dependencies: "@types/node" "*" "@types/yargs-parser@*": - version "20.2.1" - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz" - integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + version "21.0.0" + resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== "@types/yargs@^15.0.0": version "15.0.14" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06" integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ== dependencies: "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^4.2.0": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz" - integrity sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA== + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== dependencies: - "@typescript-eslint/experimental-utils" "4.29.3" - "@typescript-eslint/scope-manager" "4.29.3" + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" debug "^4.3.1" functional-red-black-tree "^1.0.1" + ignore "^5.1.8" regexpp "^3.1.0" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/experimental-utils@4.29.3": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz" - integrity sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg== +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== dependencies: "@types/json-schema" "^7.0.7" - "@typescript-eslint/scope-manager" "4.29.3" - "@typescript-eslint/types" "4.29.3" - "@typescript-eslint/typescript-estree" "4.29.3" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" "@typescript-eslint/parser@^4.2.0": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz" - integrity sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ== + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz" + integrity sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA== dependencies: - "@typescript-eslint/scope-manager" "4.29.3" - "@typescript-eslint/types" "4.29.3" - "@typescript-eslint/typescript-estree" "4.29.3" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" debug "^4.3.1" -"@typescript-eslint/scope-manager@4.29.3": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz" - integrity sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA== +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== dependencies: - "@typescript-eslint/types" "4.29.3" - "@typescript-eslint/visitor-keys" "4.29.3" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" -"@typescript-eslint/types@4.29.3": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz" - integrity sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg== +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== -"@typescript-eslint/typescript-estree@4.29.3": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz" - integrity sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag== +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== dependencies: - "@typescript-eslint/types" "4.29.3" - "@typescript-eslint/visitor-keys" "4.29.3" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" debug "^4.3.1" globby "^11.0.3" is-glob "^4.0.1" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/visitor-keys@4.29.3": - version "4.29.3" - resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz" - integrity sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA== +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== dependencies: - "@typescript-eslint/types" "4.29.3" + "@typescript-eslint/types" "4.33.0" eslint-visitor-keys "^2.0.0" "@zxing/text-encoding@0.9.0": version "0.9.0" - resolved "https://registry.npmjs.org/@zxing/text-encoding/-/text-encoding-0.9.0.tgz" + resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== abab@^2.0.3, abab@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz" - integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + version "2.0.6" + resolved "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== abbrev@1: version "1.1.1" - resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abstract-cache@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/abstract-cache/-/abstract-cache-1.0.1.tgz#136151becf5c32e0ea27f78728d073d8fe07932a" + integrity sha512-EfUeMhRUbG5bVVbrSY/ogLlFXoyfMAPxMlSP7wrEqH53d+59r2foVy9a5KjmprLKFLOfPQCNKEfpBN/nQ76chw== + dependencies: + clone "^2.1.1" + lru_map "^0.3.3" + merge-options "^1.0.0" + abstract-logging@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839" integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA== accepts@~1.3.4: - version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + version "1.3.8" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-globals@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== dependencies: acorn "^7.1.1" @@ -1799,44 +2147,52 @@ acorn-globals@^6.0.0: acorn-jsx@^5.3.1: version "5.3.2" - resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^7.1.1: version "7.2.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn@^7.1.1, acorn@^7.4.0: version "7.4.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== acorn@^8.2.4: - version "8.4.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz" - integrity sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA== + version "8.7.1" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz" + integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== adm-zip@^0.5.3: - version "0.5.5" - resolved "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.5.tgz" - integrity sha512-IWwXKnCbirdbyXSfUDvCCrmYrOHANRZcc8NcRrvTlIApdl7PwE9oGcsYvNeJPAVY1M+70b4PxXGKIf8AEuiQ6w== + version "0.5.9" + resolved "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.9.tgz" + integrity sha512-s+3fXLkeeLjZ2kLjCBwQufpI5fuN+kIGBxu6530nVQZGVol0d7Y/M88/xw9HGGUcJjKf8LutN3VPRUBq6N7Ajg== after@0.8.2: version "0.8.2" resolved "https://registry.npmjs.org/after/-/after-0.8.2.tgz" - integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + integrity sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA== agent-base@6: version "6.0.2" - resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" + 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@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-4.0.1.tgz#25091fe1573b9e0be892aeda15c7c66a545f758e" + integrity sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w== + dependencies: + clean-stack "^4.0.0" + indent-string "^5.0.0" + ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + 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" @@ -1845,9 +2201,9 @@ ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@^6.12.6: uri-js "^4.2.2" ajv@^8.0.1, ajv@^8.1.0: - version "8.6.2" - resolved "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz" - integrity sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w== + version "8.11.0" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -1855,16 +2211,16 @@ ajv@^8.0.1, ajv@^8.1.0: uri-js "^4.2.2" amqp-connection-manager@^3.7.0: - version "3.7.0" - resolved "https://registry.npmjs.org/amqp-connection-manager/-/amqp-connection-manager-3.7.0.tgz" - integrity sha512-pWlrXVQNnSV9Jsewq6wnZjddzlHI/gZroDdmMEYfsqaAUa2V2ENCXbDdoi0r/GVesxueY/Yb8nBO024lfdtdPQ== + version "3.9.0" + resolved "https://registry.npmjs.org/amqp-connection-manager/-/amqp-connection-manager-3.9.0.tgz" + integrity sha512-ZKw9ckJKz40Lc2pC7DY0NVocpzPalMaCgv0sBn+N4er2QFAJul9pIiMOm/FsPHeCzB+FulV7PckOpmZvWvewGQ== dependencies: promise-breaker "^5.0.0" -amqplib@^0.7.1: - version "0.7.1" - resolved "https://registry.npmjs.org/amqplib/-/amqplib-0.7.1.tgz" - integrity sha512-KePK3tTOLGU4emTo+PwSDMbc123jrxo13FpRpim1LzJoSlQrIBB2/kMeCC40jK/Zb0olHGaABjLqXDsdK46iLA== +amqplib@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/amqplib/-/amqplib-0.8.0.tgz#088d10bc61cc5ac5a49ac72033c7ac66c23aeb61" + integrity sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA== dependencies: bitsyntax "~0.1.0" bluebird "^3.7.2" @@ -1874,13 +2230,13 @@ amqplib@^0.7.1: url-parse "~1.5.1" analytics-node@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/analytics-node/-/analytics-node-5.0.0.tgz" - integrity sha512-eU/lPK6V3hmmv7hnJ8762zExL7WvcpVeBL6RgGZ8yQZQewk08VbbHk0M5GAlhruyh0ZT+/IBPW3Q/SYVhjexNQ== + version "5.1.2" + resolved "https://registry.npmjs.org/analytics-node/-/analytics-node-5.1.2.tgz" + integrity sha512-WZ8gkXtLuqD2Q2xEOr/2/LJiR0AnhWHfXZhfPnMZpB7vEwCsh3HapYAUmA1cPj1abrhAqBX7POWuWo/1wUu/Fw== dependencies: "@segment/loosely-validate-event" "^2.0.0" - axios "^0.21.1" - axios-retry "^3.0.2" + axios "^0.21.4" + axios-retry "3.2.0" lodash.isstring "^4.0.1" md5 "^2.2.1" ms "^2.0.0" @@ -1888,56 +2244,46 @@ analytics-node@^5.0.0: uuid "^8.3.2" ansi-align@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz" - integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw== + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== dependencies: - string-width "^3.0.0" + string-width "^4.1.0" ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + version "4.1.3" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" + integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== ansi-escapes@^4.2.1: version "4.3.2" - resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.0, ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + 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.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" anymatch@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" @@ -1945,51 +2291,51 @@ anymatch@^2.0.0: anymatch@^3.0.3, anymatch@~3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" -aproba@^1.0.3: - version "1.2.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== +"aproba@^1.0.3 || ^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== archy@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== +are-we-there-yet@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz" + integrity sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw== dependencies: delegates "^1.0.0" - readable-stream "^2.0.6" + readable-stream "^3.6.0" arg@^4.1.0: version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== args@^5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/args/-/args-5.0.1.tgz" - integrity sha512-1kqmFCFsPffavQFGt8OxJdIcETti99kySRUPMpOhaGjL6mRJn8HFU1OxKY5bMqfZKUwTQc1mZkAjmGYaVOHFtQ== + version "5.0.3" + resolved "https://registry.npmjs.org/args/-/args-5.0.3.tgz" + integrity sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA== dependencies: camelcase "5.0.0" chalk "2.4.2" @@ -1999,115 +2345,150 @@ args@^5.0.1: arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== arr-flatten@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + integrity sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q== array-parallel@~0.1.3: version "0.1.3" resolved "https://registry.npmjs.org/array-parallel/-/array-parallel-0.1.3.tgz" - integrity sha1-j3hTCJJu1apHjEfmTRszS2wMlH0= + integrity sha512-TDPTwSWW5E4oiFiKmz6RGJ/a80Y91GuLgUYuLd49+XBS75tYo8PNgaT2K/OxuQYqkoI852MDGBorg9OcUSTQ8w== array-series@~0.1.5: version "0.1.5" resolved "https://registry.npmjs.org/array-series/-/array-series-0.1.5.tgz" - integrity sha1-3103v8XC7wdV4qpPkv6ufUtaly8= + integrity sha512-L0XlBwfx9QetHOsbLDrE/vh2t018w9462HM3iaFfxRiK83aJjAt/Ja3NMkOW7FICwWTlQBa3ZbL5FKhuQWkDrg== array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== array-unique@^0.3.2: version "0.3.2" resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ== arraybuffer.slice@~0.0.7: version "0.0.7" - resolved "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz" + resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + +arrify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-3.0.0.tgz#ccdefb8eaf2a1d2ab0da1ca2ce53118759fd46bc" + integrity sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw== + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + assertion-error@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw== astral-regex@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async@^3.1.0: - version "3.2.1" - resolved "https://registry.npmjs.org/async/-/async-3.2.1.tgz" - integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg== +async@>=0.2.9, async@^3.1.0: + version "3.2.4" + resolved "https://registry.npmjs.org/async/-/async-3.2.4.tgz" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== asynckit@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== at-least-node@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== atob@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== atomic-sleep@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -available-typed-arrays@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.4.tgz" - integrity sha512-SA5mXJWrId1TaQjfxUYghbqQ/hYioKmLJvPJyDuYRtXXenFNMjj4hSSt1Cf1xsuXSXrtxrVC5Ot4eU6cOtBDdA== +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== avvio@^7.1.2: - version "7.2.2" - resolved "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz" - integrity sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw== + version "7.2.5" + resolved "https://registry.npmjs.org/avvio/-/avvio-7.2.5.tgz" + integrity sha512-AOhBxyLVdpOad3TujtC9kL/9r3HnTkxwQ5ggOsYrvvZP1cCFvzHWJd5XxZDFuTn+IN8vkKSG5SEJrd27vCSbeA== dependencies: archy "^1.0.0" debug "^4.0.0" fastq "^1.6.1" queue-microtask "^1.1.2" -axios-retry@^3.0.2: - version "3.1.9" - resolved "https://registry.npmjs.org/axios-retry/-/axios-retry-3.1.9.tgz" - integrity sha512-NFCoNIHq8lYkJa6ku4m+V1837TP6lCa7n79Iuf8/AqATAHYB0ISaAS1eyIenDOfHOLtym34W65Sjke2xjg2fsA== +axios-retry@3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/axios-retry/-/axios-retry-3.2.0.tgz" + integrity sha512-RK2cLMgIsAQBDhlIsJR5dOhODPigvel18XUv1dDXW+4k1FzebyfRk+C+orot6WPZOYFKSfhLwHPwVmTVOODQ5w== dependencies: is-retry-allowed "^1.1.0" -axios@^0.21.1, axios@^0.21.3: +axios@^0.18.0: + version "0.18.1" + resolved "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz" + integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== + dependencies: + follow-redirects "1.5.10" + is-buffer "^2.0.2" + +axios@^0.21.3, axios@^0.21.4: version "0.21.4" - resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== dependencies: follow-redirects "^1.14.0" +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + babel-jest@^26.5.2, babel-jest@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== dependencies: "@jest/transform" "^26.6.2" @@ -2121,25 +2502,25 @@ babel-jest@^26.5.2, babel-jest@^26.6.3: babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" babel-plugin-istanbul@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz" - integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + version "6.1.1" + resolved "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" "@istanbuljs/load-nyc-config" "^1.0.0" "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^4.0.0" + istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" babel-plugin-jest-hoist@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== dependencies: "@babel/template" "^7.3.3" @@ -2149,36 +2530,36 @@ babel-plugin-jest-hoist@^26.6.2: babel-plugin-parameter-decorator@^1.0.16: version "1.0.16" - resolved "https://registry.npmjs.org/babel-plugin-parameter-decorator/-/babel-plugin-parameter-decorator-1.0.16.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-parameter-decorator/-/babel-plugin-parameter-decorator-1.0.16.tgz#1c889c3a1f3bbf03801fcbc2e95b8bae7468df3f" integrity sha512-yUT2WPTUg1JaPmRGRSF557m1HJ9vdFQInRWOkiOyO5a9HhqlXffJu+fQ2xd5+qU/35ICMrrk9eWKsHCairKA9w== -babel-plugin-polyfill-corejs2@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz" - integrity sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ== +babel-plugin-polyfill-corejs2@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.2.2: - version "0.2.4" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.4.tgz" - integrity sha512-z3HnJE5TY/j4EFEa/qpQMSbcUJZ5JQi+3UFjXzn6pQCmIKc5Ug5j98SuYyH+m4xQnvKlMDIW4plLfgyVnd0IcQ== +babel-plugin-polyfill-corejs3@^0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz" + integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" - core-js-compat "^3.14.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" + core-js-compat "^3.21.0" -babel-plugin-polyfill-regenerator@^0.2.2: - version "0.2.2" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz" - integrity sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg== +babel-plugin-polyfill-regenerator@^0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.2" + "@babel/helper-define-polyfill-provider" "^0.3.1" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== dependencies: "@babel/plugin-syntax-async-generators" "^7.8.4" @@ -2196,7 +2577,7 @@ babel-preset-current-node-syntax@^1.0.0: babel-preset-jest@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== dependencies: babel-plugin-jest-hoist "^26.6.2" @@ -2205,31 +2586,31 @@ babel-preset-jest@^26.6.2: backo2@1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + integrity sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA== balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-arraybuffer@0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz" - integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= + integrity sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg== base64-js@^1.3.1: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0: +base64id@2.0.0, base64id@~2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== base@^0.11.1: version "0.11.2" - resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" @@ -2242,7 +2623,7 @@ base@^0.11.1: bcrypt@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.0.1.tgz#f1a2c20f208e2ccdceea4433df0c8b2c54ecdf71" integrity sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw== dependencies: "@mapbox/node-pre-gyp" "^1.0.0" @@ -2250,12 +2631,12 @@ bcrypt@^5.0.1: binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bitsyntax@~0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/bitsyntax/-/bitsyntax-0.1.0.tgz#b0c59acef03505de5a2ed62a2f763c56ae1d6205" integrity sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q== dependencies: buffer-more-ints "~1.0.0" @@ -2264,7 +2645,7 @@ bitsyntax@~0.1.0: bl@^4.0.3, bl@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== dependencies: buffer "^5.5.0" @@ -2273,24 +2654,39 @@ bl@^4.0.3, bl@^4.1.0: blob@0.0.5: version "0.0.5" - resolved "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz" + resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== block-stream2@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/block-stream2/-/block-stream2-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/block-stream2/-/block-stream2-2.1.0.tgz#ac0c5ef4298b3857796e05be8ebed72196fa054b" integrity sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg== dependencies: readable-stream "^3.4.0" bluebird@^3.7.2: version "3.7.2" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.1" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" + integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + boxen@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ== dependencies: ansi-align "^3.0.0" @@ -2304,7 +2700,7 @@ boxen@^4.2.0: brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -2312,7 +2708,7 @@ brace-expansion@^1.1.7: braces@^2.3.1: version "2.3.2" - resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" @@ -2326,83 +2722,149 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" + integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== + +browser-or-node@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz" + integrity sha512-0F2z/VSnLbmEeBcUrSuDH5l0HxTXdQQzLjkmBR4cYfvg1zJrKSlmIZFqyFR8oX0NrwPhy3c3HQ6i3OxMbew4Tg== + browser-process-hrtime@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.16.6, browserslist@^4.16.7: - version "4.16.8" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz" - integrity sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ== +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: - caniuse-lite "^1.0.30001251" - colorette "^1.3.0" - electron-to-chromium "^1.3.811" - escalade "^3.1.1" - node-releases "^1.1.75" + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^4.20.2, browserslist@^4.21.0: + version "4.21.1" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.1.tgz" + integrity sha512-Nq8MFCSrnJXSc88yliwlzQe3qNe3VntIjhsArW9IJOEPSHNx23FalwApUVbzAWABLhYJJ7y8AynWI/XM8OdfjQ== + dependencies: + caniuse-lite "^1.0.30001359" + electron-to-chromium "^1.4.172" + node-releases "^2.0.5" + update-browserslist-db "^1.0.4" bs-logger@0.x: version "0.2.6" - resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== dependencies: fast-json-stable-stringify "2.x" bser@2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== dependencies: node-int64 "^0.4.0" -bson@^4.4.0: - version "4.5.0" - resolved "https://registry.npmjs.org/bson/-/bson-4.5.0.tgz" - integrity sha512-WoSOKryfrKx0aqhPz/DJsUlrMlOL+hkW+469Q5z5E/EQWF2xilOH7h/s5HH4j9iLRzVDwKFwVNQ3Mba16srmlw== +bson@^4.6.3: + version "4.6.4" + resolved "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz" + integrity sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ== dependencies: buffer "^5.6.0" +buffer-crc32@^0.2.13: + version "0.2.13" + resolved "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz" - integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== buffer-from@1.x, buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== buffer-more-ints@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz#ef4f8e2dddbad429ed3828a9c55d44f05c611422" integrity sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg== +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" + integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== + buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" - resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== dependencies: base64-js "^1.3.1" ieee754 "^1.1.13" -busboy@^0.3.1: - version "0.3.1" - resolved "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz" - integrity sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw== - dependencies: - dicer "0.3.0" - cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" @@ -2417,7 +2879,7 @@ cache-base@^1.0.1: cacheable-request@^6.0.0: version "6.1.0" - resolved "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== dependencies: clone-response "^1.0.2" @@ -2430,7 +2892,7 @@ cacheable-request@^6.0.0: call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + 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" @@ -2438,40 +2900,50 @@ call-bind@^1.0.0, call-bind@^1.0.2: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-keys@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-7.0.2.tgz#d048d8c69448745bb0de6fc4c1c52a30dfbe7252" + integrity sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg== + dependencies: + camelcase "^6.3.0" + map-obj "^4.1.0" + quick-lru "^5.1.1" + type-fest "^1.2.1" + camelcase@5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: - version "6.2.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== +camelcase@^6.0.0, camelcase@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001251: - version "1.0.30001251" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz" - integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== +caniuse-lite@^1.0.30001359: + version "1.0.30001361" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001361.tgz" + integrity sha512-ybhCrjNtkFji1/Wto6SSJKkWk6kZgVQsDq5QI83SafsF6FXv2JB4df9eEdH6g8sdGgqTXrFLjAxqBGgYoU3azQ== capture-exit@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== dependencies: rsvp "^4.8.4" cassandra-driver@^4.6.0: - version "4.6.3" - resolved "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.6.3.tgz" - integrity sha512-npW670TXjTHrdb15LUFN01wssb9vvz6SuNYcppesoKcUXx3Q29nXVhRtnvsnkG0BaSnDGvCCR4udrzYLsbh+sg== + version "4.6.4" + resolved "https://registry.yarnpkg.com/cassandra-driver/-/cassandra-driver-4.6.4.tgz#a916018d2dfee73d00e51cedac84c44aff07bcbd" + integrity sha512-SksbIK0cZ2QZRx8ti7w+PnLqldyY+6kU2gRWFChwXFTtrD/ce8cQICDEHxyPwx+DeILwRnMrPf9cjUGizYw9Vg== dependencies: "@types/long" "^4.0.0" "@types/node" ">=8" @@ -2479,20 +2951,21 @@ cassandra-driver@^4.6.0: long "^2.2.0" chai@^4.2.0: - version "4.3.4" - resolved "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz" - integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + version "4.3.6" + resolved "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" + loupe "^2.3.1" pathval "^1.1.1" type-detect "^4.0.5" chalk@2.4.2, chalk@^2.0.0: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + 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" @@ -2501,7 +2974,7 @@ chalk@2.4.2, chalk@^2.0.0: chalk@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== dependencies: ansi-styles "^4.1.0" @@ -2509,7 +2982,7 @@ chalk@^3.0.0: chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -2517,23 +2990,48 @@ chalk@^4.0.0, chalk@^4.1.0: char-regex@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== charenc@0.0.2: version "0.0.2" resolved "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== check-error@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.12" + resolved "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" chokidar@^3.2.2, chokidar@^3.5.1: - version "3.5.2" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + version "3.5.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -2547,32 +3045,40 @@ chokidar@^3.2.2, chokidar@^3.5.1: chownr@^1.1.1: version "1.1.4" - resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chownr@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== ci-info@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + cjs-module-lexer@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== class-transformer@^0.3.1: - version "0.3.1" - resolved "https://registry.npmjs.org/class-transformer/-/class-transformer-0.3.1.tgz" - integrity sha512-cKFwohpJbuMovS8xVLmn8N2AUbAuc8pVo4zEfsUVo8qgECOogns1WVk/FkOZoxhOPTyTYFckuoH+13FO+MQ8GA== + version "0.3.2" + resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.3.2.tgz#779ef5f124784324b40f8e927c774bd96cdecd4b" + integrity sha512-9QY6QXBH/+Gt1C3HBmJCrgY6+EFpIa6aLjfDnlXFx0zQl/HjrCE7qoaI0srNrxpMIfsobCpgUdDG5JYtJOpVsw== class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" @@ -2580,33 +3086,40 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-stack@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-4.2.0.tgz#c464e4cde4ac789f4e0735c5d75beb49d7b30b31" + integrity sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg== + dependencies: + escape-string-regexp "5.0.0" + cli-boxes@^2.2.0: version "2.2.1" - resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== cli-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== dependencies: restore-cursor "^3.1.0" cli-spinners@^2.5.0: - version "2.6.0" - resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz" - integrity sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q== + version "2.6.1" + resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz" + integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== cli-table@^0.3.6: - version "0.3.6" - resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz" - integrity sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ== + version "0.3.11" + resolved "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz" + integrity sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ== dependencies: colors "1.0.3" cliui@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: string-width "^4.2.0" @@ -2615,7 +3128,7 @@ cliui@^6.0.0: cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -2625,135 +3138,140 @@ cliui@^7.0.2: clone-response@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== dependencies: mimic-response "^1.0.0" +clone@2.x, clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== + clone@^1.0.2: version "1.0.4" resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +cluster-key-slot@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" + integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== co@^4.6.0: version "4.6.0" resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== collect-v8-coverage@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + integrity sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw== dependencies: map-visit "^1.0.0" object-visit "^1.0.0" color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + 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.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + 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, color-name@^1.0.0: +color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@~1.1.4: +color-name@^1.0.0, color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.6.0: - version "1.6.0" - resolved "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz" - integrity sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA== +color-string@^1.9.0: + version "1.9.1" + resolved "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" -color@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/color/-/color-4.0.1.tgz" - integrity sha512-rpZjOKN5O7naJxkH2Rx1sZzzBgaiWECc6BYXjeCE6kF0kcASJYbUq02u7JqIHwCb/j3NhV+QhRL2683aICeGZA== +color-support@^1.1.2: + version "1.1.3" + resolved "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + +color@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.org/color/-/color-4.2.3.tgz" + integrity sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A== dependencies: color-convert "^2.0.1" - color-string "^1.6.0" - -colorette@^1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz" - integrity sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w== + color-string "^1.9.0" colors@1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= + integrity sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw== combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" +commander@^2.19.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + component-bind@1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz" - integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= - -component-emitter@1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz" - integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + integrity sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw== component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== component-inherit@0.0.3: version "0.0.3" resolved "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz" - integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + integrity sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA== component-type@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/component-type/-/component-type-1.2.1.tgz" - integrity sha1-ikeQFwAjjk/DIml3EjAibyS0Fak= + integrity sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg== concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== config@^3.3.2: - version "3.3.6" - resolved "https://registry.npmjs.org/config/-/config-3.3.6.tgz" - integrity sha512-Hj5916C5HFawjYJat1epbyY2PlAgLpBtDUlr0MxGLgo3p5+7kylyvnRY18PqJHgnNWXcdd0eWDemT7eYWuFgwg== + version "3.3.7" + resolved "https://registry.npmjs.org/config/-/config-3.3.7.tgz" + integrity sha512-mX/n7GKDYZMqvvkY6e6oBY49W8wxdmQt+ho/5lhwFDXqQW9gI+Ahp8EKp8VAbISPnmf2+Bv5uZK7lKXZ6pf1aA== dependencies: json5 "^2.1.1" configstore@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA== dependencies: dot-prop "^5.2.0" @@ -2763,69 +3281,145 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" -console-control-strings@^1.0.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== content-disposition@^0.5.3: - version "0.5.3" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + version "0.5.4" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" -cookie@^0.4.0, cookie@^0.4.1, cookie@~0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== +cookie@^0.4.1, cookie@~0.4.1: + version "0.4.2" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookie@^0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== cookiejar@^2.1.0: - version "2.1.2" - resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + version "2.1.3" + resolved "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== -core-js-compat@^3.14.0, core-js-compat@^3.16.0: - version "3.16.2" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.16.2.tgz" - integrity sha512-4lUshXtBXsdmp8cDWh6KKiHUg40AjiuPD3bOWkNVsr1xkAhpUqCjaZ8lB1bKx9Gb5fXcbRbFJ4f4qpRIRTuJqQ== +core-js-compat@^3.21.0, core-js-compat@^3.22.1: + version "3.23.3" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.23.3.tgz" + integrity sha512-WSzUs2h2vvmKsacLHNTdpyOC9k43AEhcGoFlVgCY4L7aw98oSBKtPL6vD0/TqZjRWRQYdDSLkzZIni4Crbbiqw== dependencies: - browserslist "^4.16.7" + browserslist "^4.21.0" semver "7.0.0" core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + version "1.0.3" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@~2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +cp-file@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-9.1.0.tgz#e98e30db72d57d47b5b1d444deb70d05e5684921" + integrity sha512-3scnzFj/94eb7y4wyXRWwvzLFaQp87yyfTnChIjlfYrVqp5lVO3E2hIJMeQIltUT0K2ZAB3An1qXcBmwGyvuwA== + dependencies: + graceful-fs "^4.1.2" + make-dir "^3.0.0" + nested-error-stacks "^2.0.0" + p-event "^4.1.0" + +cpy-cli@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/cpy-cli/-/cpy-cli-4.2.0.tgz#d60bf9ac776486af20aac2fa4fb95f8f10b35ce8" + integrity sha512-b04b+cbdr29CdpREPKw/itrfjO43Ty0Aj7wRM6M6LoE4GJxZJCk9Xp+Eu1IqztkKh3LxIBt1tDplENsa6KYprg== + dependencies: + cpy "^9.0.0" + meow "^10.1.2" + +cpy@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cpy/-/cpy-9.0.1.tgz#7f3ad0ad5bafe0bc70645c4bb567969927cadb9f" + integrity sha512-D9U0DR5FjTCN3oMTcFGktanHnAG5l020yvOCR1zKILmAyPP7I/9pl6NFgRbDcmSENtbK1sQLBz1p9HIOlroiNg== + dependencies: + arrify "^3.0.0" + cp-file "^9.1.0" + globby "^13.1.1" + junk "^4.0.0" + micromatch "^4.0.4" + nested-error-stacks "^2.1.0" + p-filter "^3.0.0" + p-map "^5.3.0" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" create-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-spawn@^4.0.0: version "4.0.2" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz" - integrity sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE= + integrity sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA== dependencies: lru-cache "^4.0.1" which "^1.2.9" cross-spawn@^6.0.0: version "6.0.5" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" @@ -2836,7 +3430,7 @@ cross-spawn@^6.0.0: cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -2846,33 +3440,77 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: crypt@0.0.2: version "0.0.2" resolved "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== + +crypto-browserify@^3.12.0: + version "3.12.0" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" crypto-random-string@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +css-select@^4.2.1: + version "4.3.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== + dependencies: + boolbase "^1.0.0" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" + +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + cssom@^0.4.4: version "0.4.4" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== cssom@~0.3.6: version "0.3.8" - resolved "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== cssstyle@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== dependencies: cssom "~0.3.6" data-urls@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== dependencies: abab "^2.0.3" @@ -2880,137 +3518,144 @@ data-urls@^2.0.0: whatwg-url "^8.0.0" dateformat@^4.5.1: - version "4.5.1" - resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz" - integrity sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q== + version "4.6.3" + resolved "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@~2.6.9: +debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@~2.6.9: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@~4.3.1: - version "4.3.2" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@~4.3.1, debug@~4.3.2: + version "4.3.4" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@~3.1.0: +debug@=3.1.0, debug@~3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== dependencies: ms "2.0.0" -debug@~4.1.0: - version "4.1.1" - resolved "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== +debug@^3.1.0, debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== dependencies: ms "^2.1.1" -decamelize@^1.2.0: +decamelize-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-5.0.1.tgz#db11a92e58c741ef339fb0a2868d8a06a9a7b1e9" + integrity sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA== decimal.js@^10.2.1: version "10.3.1" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + integrity sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA== dependencies: mimic-response "^1.0.0" -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - mimic-response "^2.0.0" + mimic-response "^3.1.0" deep-eql@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== dependencies: type-detect "^4.0.0" deep-extend@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + version "0.1.4" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== deep-object-diff@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.0.tgz" - integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== + version "1.1.7" + resolved "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.7.tgz" + integrity sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg== deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== defaults@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA== dependencies: clone "^1.0.2" defer-to-connect@^1.0.1: version "1.1.3" - resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.3, define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" define-property@^0.2.5: version "0.2.5" resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + integrity sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA== dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + integrity sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA== dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" @@ -3019,103 +3664,178 @@ define-property@^2.0.2: delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== delegates@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== denque@^1.5.0: version "1.5.1" - resolved "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf" integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw== +denque@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz" + integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== + depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" destroy@~1.0.4: version "1.0.4" resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + integrity sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg== -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= +detect-libc@^2.0.0, detect-libc@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== detect-newline@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== -dicer@0.3.0: - version "0.3.0" - resolved "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz" - integrity sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA== - dependencies: - streamsearch "0.1.2" - diff-sequences@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== diff@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" +discontinuous-range@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" + integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ== + doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" +dom-serializer@^1.0.1: + version "1.4.1" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.2.0" + entities "^2.0.0" + +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + domexception@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== dependencies: webidl-conversions "^5.0.0" +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== + dependencies: + domelementtype "^2.2.0" + +domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^2.5.2, domutils@^2.8.0: + version "2.8.0" + resolved "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz" + integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== + dependencies: + dom-serializer "^1.0.1" + domelementtype "^2.2.0" + domhandler "^4.2.0" + +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + dot-prop@^5.2.0: version "5.3.0" - resolved "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: is-obj "^2.0.0" duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + version "0.1.5" + resolved "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== duplexer@~0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== dynamic-dedupe@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz" - integrity sha1-BuRMIj9eTpTXjvnbI6ZRXOL5YqE= + integrity sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ== dependencies: xtend "^4.0.0" ecdsa-sig-formatter@1.0.11: version "1.0.11" - resolved "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== dependencies: safe-buffer "^5.0.1" @@ -3123,48 +3843,70 @@ ecdsa-sig-formatter@1.0.11: ee-first@1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.3.811: - version "1.3.816" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.816.tgz" - integrity sha512-/AvJPIJldO0NkwkfpUD7u1e4YEGRFBQpFuvl9oGCcVgWOObsZB1loxVGeVUJB9kmvfsBUUChPYdgRzx6+AKNyg== + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.172: + version "1.4.176" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.176.tgz" + integrity sha512-92JdgyRlcNDwuy75MjuFSb3clt6DGJ2IXSpg0MCjKd3JV9eSmuUAIyWiGAp/EtT0z2D4rqbYqThQLV90maH3Zw== + +elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emittery@^0.7.1: version "0.7.2" - resolved "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== +emoji-name-map@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/emoji-name-map/-/emoji-name-map-1.2.9.tgz#32a0788e748d9c7185a29a000102fb263fe2892d" + integrity sha512-MSM8y6koSqh/2uEMI2VoKA+Ac0qL5RkgFGP/pzL6n5FOrOJ7FOZFxgs7+uNpqA+AT+WmdbMPXkd3HnFXXdz4AA== + dependencies: + emojilib "^2.0.2" + iterate-object "^1.3.1" + map-o "^2.0.1" emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emojilib@^2.0.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/emojilib/-/emojilib-2.4.0.tgz#ac518a8bb0d5f76dda57289ccb2fdf9d39ae721e" + integrity sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== encoding-negotiator@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/encoding-negotiator/-/encoding-negotiator-2.0.1.tgz#79871bb5473b81f6a0670e8de5303fb5ee0868a3" integrity sha512-GSK7qphNR4iPcejfAlZxKDoz3xMhnspwImK+Af5WhePS9jUpK/Oh7rUdyENWu+9rgDflOCTmAojBsgsvM8neAQ== end-of-stream@^1.1.0, end-of-stream@^1.4.1, end-of-stream@^1.4.4: version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" + 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" engine.io-client@~3.5.0: version "3.5.2" - resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.5.2.tgz#0ef473621294004e9ceebe73cef0af9e36f2f5fa" integrity sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA== dependencies: component-emitter "~1.3.0" @@ -3181,7 +3923,7 @@ engine.io-client@~3.5.0: engine.io-parser@~2.2.0: version "2.2.1" - resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.2.1.tgz#57ce5611d9370ee94f99641b589f94c97e4f5da7" integrity sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg== dependencies: after "0.8.2" @@ -3190,58 +3932,83 @@ engine.io-parser@~2.2.0: blob "0.0.5" has-binary2 "~1.0.2" -engine.io@~3.5.0: - version "3.5.0" - resolved "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz" - integrity sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA== +engine.io-parser@~5.0.3: + version "5.0.4" + resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz" + integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg== + +engine.io@~6.2.0: + version "6.2.0" + resolved "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz" + integrity sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg== dependencies: + "@types/cookie" "^0.4.1" + "@types/cors" "^2.8.12" + "@types/node" ">=10.0.0" accepts "~1.3.4" base64id "2.0.0" cookie "~0.4.1" - debug "~4.1.0" - engine.io-parser "~2.2.0" - ws "~7.4.2" + cors "~2.8.5" + debug "~4.3.1" + engine.io-parser "~5.0.3" + ws "~8.2.3" enquirer@^2.3.5: version "2.3.6" - resolved "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz" + 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" +entities@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" + integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== + +entities@^4.2.0, entities@^4.3.0: + version "4.3.0" + resolved "https://registry.npmjs.org/entities/-/entities-4.3.0.tgz" + integrity sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg== + error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" + 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.5: - version "1.18.5" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz" - integrity sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA== +es-abstract@^1.19.0, es-abstract@^1.19.5, es-abstract@^1.20.0: + version "1.20.1" + resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz" + integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" function-bind "^1.1.1" + function.prototype.name "^1.1.5" get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" has "^1.0.3" - has-symbols "^1.0.2" + has-property-descriptors "^1.0.0" + has-symbols "^1.0.3" internal-slot "^1.0.3" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.3" - is-string "^1.0.6" - object-inspect "^1.11.0" + is-callable "^1.2.4" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-weakref "^1.0.2" + object-inspect "^1.12.0" object-keys "^1.1.1" object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" + regexp.prototype.flags "^1.4.3" + string.prototype.trimend "^1.0.5" + string.prototype.trimstart "^1.0.5" + unbox-primitive "^1.0.2" es-to-primitive@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" + 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" @@ -3250,42 +4017,47 @@ es-to-primitive@^1.2.1: es6-error@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-goat@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== escape-html@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz" + 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.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escodegen@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== dependencies: esprima "^4.0.1" @@ -3297,21 +4069,21 @@ escodegen@^2.0.0: eslint-config-prettier@^6.15.0: version "6.15.0" - resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== dependencies: get-stdin "^6.0.0" eslint-plugin-prettier@^3.1.4: version "3.4.1" - resolved "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5" integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g== dependencies: prettier-linter-helpers "^1.0.0" eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + 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" @@ -3319,31 +4091,31 @@ eslint-scope@^5.1.1: eslint-utils@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz" + 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-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== dependencies: eslint-visitor-keys "^2.0.0" eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz" + 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.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== eslint@^7.10.0: version "7.32.0" - resolved "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== dependencies: "@babel/code-frame" "7.12.11" @@ -3389,7 +4161,7 @@ eslint@^7.10.0: espree@^7.3.0, espree@^7.3.1: version "7.3.1" - resolved "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz" + 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" @@ -3398,47 +4170,52 @@ espree@^7.3.0, espree@^7.3.1: esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" + 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.npmjs.org/esquery/-/esquery-1.4.0.tgz" + 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.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + 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.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + 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.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + version "5.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +eta@^1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/eta/-/eta-1.12.3.tgz#2982d08adfbef39f9fa50e2fbd42d7337e7338b1" + integrity sha512-qHixwbDLtekO/d51Yr4glcaUJCIjGVJyTzuqV4GPlgZo1YpgOKG+avQynErZIYrfM6JIJdtiG2Kox8tbb+DoGg== + etag@~1.8.1: version "1.8.1" resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== event-stream@=3.3.4: version "3.3.4" resolved "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz" - integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE= + integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g== dependencies: duplexer "~0.1.1" from "~0" @@ -3448,14 +4225,22 @@ event-stream@=3.3.4: stream-combiner "~0.0.4" through "~2.3.1" +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + exec-sh@^0.3.2: version "0.3.6" - resolved "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== execa@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== dependencies: cross-spawn "^6.0.0" @@ -3468,7 +4253,7 @@ execa@^1.0.0: execa@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== dependencies: cross-spawn "^7.0.0" @@ -3484,12 +4269,12 @@ execa@^4.0.0: exit@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + integrity sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA== dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -3501,12 +4286,12 @@ expand-brackets@^2.1.4: expand-template@^2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== expect@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== dependencies: "@jest/types" "^26.6.2" @@ -3519,26 +4304,26 @@ expect@^26.6.2: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + integrity sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q== dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" extend@^3.0.0: version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== extglob@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" @@ -3552,23 +4337,34 @@ extglob@^2.0.4: fast-decode-uri-component@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + 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.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.1.1: - version "3.2.7" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.11: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3578,13 +4374,13 @@ fast-glob@^3.1.1: fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-json-stringify@^2.5.2: - version "2.7.8" - resolved "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.8.tgz" - integrity sha512-HRSGwEWe0/5EH7GEaWg1by4dInnBb1WFf4umMPr+lL5xb0VP0VbpNGklp4L0/BseD+BmtIZpjqJjnLFwaQ21dg== + version "2.7.13" + resolved "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz" + integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA== dependencies: ajv "^6.11.0" deepmerge "^4.2.2" @@ -3594,33 +4390,46 @@ fast-json-stringify@^2.5.2: fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fast-proxy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-proxy/-/fast-proxy-2.1.0.tgz#f4544e1db5fa72cb584a6a28497717cc88c561a6" + integrity sha512-ihCPWH8j4pfSIULx6evT39RzZjCkGScCVn2BRyJElDu3v96NCWjPJPX8Olnzxv30mMQUEEijonTKroqCVpXjUQ== + dependencies: + end-of-stream "^1.4.4" + pump "^3.0.0" + semver "^7.3.5" + tiny-lru "^7.0.6" + undici "^3.3.6" fast-redact@^3.0.0: - version "3.0.1" - resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz" - integrity sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw== + version "3.1.1" + resolved "https://registry.npmjs.org/fast-redact/-/fast-redact-3.1.1.tgz" + integrity sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A== fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.0.8: - version "2.0.8" - resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz" - integrity sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag== + version "2.1.1" + resolved "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fast-xml-parser@^3.17.5: - version "3.19.0" - resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.19.0.tgz" - integrity sha512-4pXwmBplsCPv8FOY1WRakF970TjNGnGnfbOnLqjlYvMiF1SR3yOHyxMR/YCXpPTOspNF5gwudqktIP4VsWkvBg== + version "3.21.1" + resolved "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz" + integrity sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg== + dependencies: + strnum "^1.0.4" fastfall@^1.5.0: version "1.5.1" resolved "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz" - integrity sha1-P+4DMxpJ0dObPN96XpzWb0dee5Q= + integrity sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q== dependencies: reusify "^1.0.0" fastify-cors@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/fastify-cors/-/fastify-cors-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/fastify-cors/-/fastify-cors-4.1.0.tgz#ae6e2533f42b033a35da85ed3d585aafd56c2210" integrity sha512-Vr4AgypDkRwG16cs1ORnYItZx6FMN+gCpHvP3/nzNZL1HFzf7U/NaSgmC784VqtK8yiqSXZEoTGCsmzeSp8JVw== dependencies: fastify-plugin "^2.0.0" @@ -3628,19 +4437,27 @@ fastify-cors@^4.1.0: fastify-error@^0.3.0: version "0.3.1" - resolved "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz" + resolved "https://registry.yarnpkg.com/fastify-error/-/fastify-error-0.3.1.tgz#8eb993e15e3cf57f0357fc452af9290f1c1278d2" integrity sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ== -fastify-formbody@^5.0.0: - version "5.1.0" - resolved "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-5.1.0.tgz" - integrity sha512-dLFQ8gMQeLuV45J72svDbrp6CZ3hxsaiK2dd3vzoiCs9wEmCSbbJV+/afQl1cfvf19+NfCIzYVQIg1r4yO4Epw== +"fastify-formbody-deprecated@npm:fastify-formbody@5.2.0": + version "5.2.0" + resolved "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-5.2.0.tgz" + integrity sha512-d8Y5hCL82akPyoFiXh2wYOm3es0pV9jqoPo3pO9OV2cNF0cQx39J5WAVXzCh4MSt9Z2qF4Fy5gHlvlyESwjtvg== dependencies: fastify-plugin "^3.0.0" +fastify-formbody@^5.0.0: + version "5.3.0" + resolved "https://registry.npmjs.org/fastify-formbody/-/fastify-formbody-5.3.0.tgz" + integrity sha512-7cjFV2HE/doojyfTwCLToIFD6Hmbw2jVTbfqZ2lbUZznQWlSXu+MBQgqBU8T2nHcMfqSi9vx6PyX0LwTehuKkg== + dependencies: + fastify-formbody-deprecated "npm:fastify-formbody@5.2.0" + process-warning "^1.0.0" + fastify-jwt@^2.2.0: version "2.5.0" - resolved "https://registry.npmjs.org/fastify-jwt/-/fastify-jwt-2.5.0.tgz" + resolved "https://registry.yarnpkg.com/fastify-jwt/-/fastify-jwt-2.5.0.tgz#6cd4d9b979638edccb6fd3d7f9972c0157cd3bf7" integrity sha512-QXOSfo65OxSk30TTecLh8J0LEmuQJwRPqXMDvPA9HfLdsX/xPdq/QSvQFvR5Aj1kwrFFjsyb1SNAOQmbkmpj4w== dependencies: "@types/jsonwebtoken" "^8.5.0" @@ -3649,142 +4466,168 @@ fastify-jwt@^2.2.0: jsonwebtoken "^8.5.1" steed "^1.1.3" -fastify-multipart@*, fastify-multipart@4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/fastify-multipart/-/fastify-multipart-4.0.3.tgz" - integrity sha512-RyouqARMlSgTudcPCDmxVN07YEDWojT5iQ+AkjX7DcQ+Y65hHzrOqrNveu5gs+lEIg5afGaH5ESHCNCOZYlveQ== +"fastify-multipart-deprecated@npm:fastify-multipart@5.3.1", fastify-multipart@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/fastify-multipart/-/fastify-multipart-5.3.1.tgz#05254d8aa43dc02af6ce01f4e513a6c30bea2886" + integrity sha512-c2pnGfkJmiNpYqzFYT2QfBg/06AxG531O+n1elqc8YUbWPRzufdqn3yfGAIV3RA7J4Vnf7Pfvgx0iaWqaRTOVA== dependencies: - busboy "^0.3.1" + "@fastify/busboy" "^1.0.0" deepmerge "^4.2.2" end-of-stream "^1.4.4" fastify-error "^0.3.0" fastify-plugin "^3.0.0" hexoid "^1.0.0" + secure-json-parse "^2.4.0" stream-wormhole "^1.1.0" +fastify-multipart@*: + version "5.4.0" + resolved "https://registry.yarnpkg.com/fastify-multipart/-/fastify-multipart-5.4.0.tgz#4dcb5e7581ca8e0c95163b4088e8a45feb9e2259" + integrity sha512-Pafy4mtcuFUnFM/t0kgCdL854KIEoDymNVdv4nD7uBfV7lBCQq/NVEuNnaNXAbuCTpeXzYRzi50lSDa9ZM838A== + dependencies: + fastify-multipart-deprecated "npm:fastify-multipart@5.3.1" + process-warning "^1.0.0" + fastify-plugin@^2.0.0, fastify-plugin@^2.3.4: version "2.3.4" - resolved "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-2.3.4.tgz" + resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-2.3.4.tgz#b17abdc36a97877d88101fb86ad8a07f2c07de87" integrity sha512-I+Oaj6p9oiRozbam30sh39BiuiqBda7yK2nmSPVwDCfIBlKnT8YB3MY+pRQc2Fcd07bf6KPGklHJaQ2Qu81TYQ== dependencies: semver "^7.3.2" -fastify-plugin@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-3.0.0.tgz" - integrity sha512-ZdCvKEEd92DNLps5n0v231Bha8bkz1DjnPP/aEz37rz/q42Z5JVLmgnqR4DYuNn3NXAO3IDCPyRvgvxtJ4Ym4w== +fastify-plugin@^3.0.0, fastify-plugin@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.1.tgz#79e84c29f401020f38b524f59f2402103fd21ed2" + integrity sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA== -fastify-sensible@^3.0.1: - version "3.1.1" - resolved "https://registry.npmjs.org/fastify-sensible/-/fastify-sensible-3.1.1.tgz" - integrity sha512-qWGsLEcc8VmLpbbWY7VJwXwWISsGBH9H4J2QeIc+l5Ov3a1lYs7ZaSnr0X8dkffdvzr9iy8wQyIuthpKTy5sZA== +fastify-sensible@=3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/fastify-sensible/-/fastify-sensible-3.0.1.tgz#9577ecb1c499b72b80ffabf6fae3b2d2b26f2dbc" + integrity sha512-XVgrQySnpNq6FTUEhLLyA0i6eB7DKF6OJV05gxCDQ008cEgzOs97L/TOd1tT3fgRf3Z6tyA2zb/wMdFX5o1C2Q== dependencies: + "@types/node" "^14.0.1" fast-deep-equal "^3.1.1" - fastify-plugin "^3.0.0" + fastify-plugin "^2.0.0" forwarded "^0.1.2" http-errors "^1.7.3" type-is "^1.6.18" vary "^1.1.2" -fastify-static@^4.0.0: - version "4.2.3" - resolved "https://registry.npmjs.org/fastify-static/-/fastify-static-4.2.3.tgz" - integrity sha512-uFRgwYXZwLKyaMrByf10efO+HTjAPqyQOlUthoGljQKGCfbwUeTeE7EHadsDWeN7NMeqBE617RamVh9uqatuUw== +fastify-socket.io@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fastify-socket.io/-/fastify-socket.io-3.0.0.tgz#9fa74b4fbba48675ea4367e9751d855b092c9a14" + integrity sha512-rVNs6NPY6ZoUQFMxZCRQreQpNyNkyKXrTbzXXzw55/grEegTW0meKBI02JAyWd2/T+k7nKB+d/7aNhYlB/Q5Bg== + dependencies: + fastify-plugin "^3.0.0" + +"fastify-static-deprecated@npm:fastify-static@4.6.1": + version "4.6.1" + resolved "https://registry.yarnpkg.com/fastify-static/-/fastify-static-4.6.1.tgz#687131da76f1d4391fb8b47f71ea2118cdc85803" + integrity sha512-vy7N28U4AMhuOim12ZZWHulEE6OQKtzZbHgiB8Zj4llUuUQXPka0WHAQI3njm1jTCx4W6fixUHfpITxweMtAIA== dependencies: content-disposition "^0.5.3" encoding-negotiator "^2.0.1" fastify-plugin "^3.0.0" glob "^7.1.4" + p-limit "^3.1.0" readable-stream "^3.4.0" send "^0.17.1" +fastify-static@*, fastify-static@^4.0.0, fastify-static@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/fastify-static/-/fastify-static-4.7.0.tgz#e802658d69c1dcddb380b9afc2456d467a3494be" + integrity sha512-zZhCfJv/hkmud2qhWqpU3K9XVAuy3+IV8Tp9BC5J5U+GyA2XwoB6h8lh9GqpEIqdXOw01WyWQllV7dOWVyAlXg== + dependencies: + fastify-static-deprecated "npm:fastify-static@4.6.1" + process-warning "^1.0.0" + fastify-swagger@^4.12.6: - version "4.12.6" - resolved "https://registry.npmjs.org/fastify-swagger/-/fastify-swagger-4.12.6.tgz" - integrity sha512-XuHyi+aPQETMsB5oOw5m8j8hror/08MSa/7Gpxon3Mu2ZtlulG8q8/XmBGB1UM0WDRifGw456IgO7kVQVPLU8A== + version "4.17.1" + resolved "https://registry.npmjs.org/fastify-swagger/-/fastify-swagger-4.17.1.tgz" + integrity sha512-VUo8W7C+YIw/e+YbNTc15Nhl5xa9MpRMPFDKkRgwvgh0cn1mvGgT34sk77mlDclKwiEO471ayW+EFSL0OYXE1A== dependencies: fastify-plugin "^3.0.0" fastify-static "^4.0.0" js-yaml "^4.0.0" json-schema-resolver "^1.3.0" - openapi-types "^9.1.0" - -fastify-warning@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/fastify-warning/-/fastify-warning-0.2.0.tgz" - integrity sha512-s1EQguBw/9qtc1p/WTY4eq9WMRIACkj+HTcOIK1in4MV5aFaQC9ZCIt0dJ7pr5bIf4lPpHvAtP2ywpTNgs7hqw== + openapi-types "^10.0.0" fastify-websocket@^2.0.11: version "2.1.0" - resolved "https://registry.npmjs.org/fastify-websocket/-/fastify-websocket-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fastify-websocket/-/fastify-websocket-2.1.0.tgz#3e0e83d09512e19d5084f0440d9767e289cf91c2" integrity sha512-u5zClCarOHctvzKq76Gc0rDwtWfU7pw+JGYETfSu77YzZ/uzXLDX4jB70vLliUc3nqK0zXFRDK2/KnEnfdF9Kw== dependencies: fastify-plugin "^3.0.0" find-my-way "^3.0.5" ws "^7.4.2" -fastify@3.22.1: - version "3.22.1" - resolved "https://registry.npmjs.org/fastify/-/fastify-3.22.1.tgz" - integrity sha512-TeA4+TzI7VuJrjTNqoxtSXwPEYfCwpT8j9Z3j9WrL8nrt+1bE9G0rP9hLJyvbg4it56p68YsHVhKOee69xyfmA== +fastify@^3.27.1: + version "3.29.0" + resolved "https://registry.npmjs.org/fastify/-/fastify-3.29.0.tgz" + integrity sha512-zXSiDTdHJCHcmDrSje1f1RfzTmUTjMtHnPhh6cdokgfHhloQ+gy0Du+KlEjwTbcNC3Djj4GAsBzl6KvfI9Ah2g== dependencies: "@fastify/ajv-compiler" "^1.0.0" + "@fastify/error" "^2.0.0" abstract-logging "^2.0.0" avvio "^7.1.2" fast-json-stringify "^2.5.2" - fastify-error "^0.3.0" - fastify-warning "^0.2.0" - find-my-way "^4.1.0" + find-my-way "^4.5.0" flatstr "^1.0.12" light-my-request "^4.2.0" pino "^6.13.0" + process-warning "^1.0.0" proxy-addr "^2.0.7" rfdc "^1.1.4" secure-json-parse "^2.0.0" semver "^7.3.2" - tiny-lru "^7.0.0" + tiny-lru "^8.0.1" fastparallel@^2.2.0: - version "2.4.0" - resolved "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.0.tgz" - integrity sha512-sacwQ7wwKlQXsa7TN24UvMBLZNLmVcPhmxccC9riFqb3N+fSczJL8eWdnZodZ/KijGVgNBBfvF/NeXER08uXnQ== + version "2.4.1" + resolved "https://registry.yarnpkg.com/fastparallel/-/fastparallel-2.4.1.tgz#0d984a5813ffa67f30b4a5cb4cb8cbe61c7ee5a5" + integrity sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q== dependencies: reusify "^1.0.4" xtend "^4.0.2" fastq@^1.3.0, fastq@^1.6.0, fastq@^1.6.1: - version "1.12.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz" - integrity sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg== + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== dependencies: reusify "^1.0.4" fastseries@^1.7.0: version "1.7.2" resolved "https://registry.npmjs.org/fastseries/-/fastseries-1.7.2.tgz" - integrity sha1-0izhO5Qz3/M4jZHb1ri9qbIaD0s= + integrity sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ== dependencies: reusify "^1.0.0" xtend "^4.0.0" fb-watchman@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== dependencies: bser "2.1.1" file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" +file-type@^7.6.0: + version "7.7.1" + resolved "https://registry.npmjs.org/file-type/-/file-type-7.7.1.tgz" + integrity sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + integrity sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ== dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" @@ -3793,41 +4636,58 @@ fill-range@^4.0.0: fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" find-my-way@^3.0.5: version "3.0.5" - resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-3.0.5.tgz" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-3.0.5.tgz#f71c5ef1b4865401e1b97ba428121a8f55439eec" integrity sha512-FweGg0cv1sBX8z7WhvBX5B5AECW4Zdh/NiB38Oa0qwSNIyPgRBCl/YjxuZn/rz38E/MMBHeVKJ22i7W3c626Gg== dependencies: fast-decode-uri-component "^1.0.1" safe-regex2 "^2.0.0" semver-store "^0.3.0" -find-my-way@^4.1.0: - version "4.3.3" - resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-4.3.3.tgz" - integrity sha512-5E4bRdaATB1MewjOCBjx4xvD205a4t2ripCnXB+YFhYEJ0NABtrcC7XLXLq0TPoFe/WYGUFqys3Qk3HCOGeNcw== +find-my-way@^4.5.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-4.5.1.tgz#758e959194b90aea0270db18fff75e2fceb2239f" + integrity sha512-kE0u7sGoUFbMXcOG/xpkmz4sRLCklERnBcg7Ftuu1iAxsfEt2S46RLJ3Sq7vshsEy2wJT2hZxE58XZK27qa8kg== + dependencies: + fast-decode-uri-component "^1.0.1" + fast-deep-equal "^3.1.3" + safe-regex2 "^2.0.0" + semver-store "^0.3.0" + +find-my-way@^5.2.0: + version "5.6.0" + resolved "https://registry.npmjs.org/find-my-way/-/find-my-way-5.6.0.tgz" + integrity sha512-pFTzbl2u+iSrvVOGtfKenvDmNIhNtEcwbzvRMfx3TGO69fbO5udgTKtAZAaUfIUrHQWLkkWvhNafNz179kaCIw== dependencies: fast-decode-uri-component "^1.0.1" fast-deep-equal "^3.1.3" safe-regex2 "^2.0.0" - semver-store "^0.3.0" find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + 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" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + flat-cache@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: flatted "^3.1.0" @@ -3835,39 +4695,61 @@ flat-cache@^3.0.4: flatstr@^1.0.12: version "1.0.12" - resolved "https://registry.npmjs.org/flatstr/-/flatstr-1.0.12.tgz" + 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.2.2" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz" - integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== + version "3.2.6" + resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.6.tgz" + integrity sha512-0sQoMh9s0BYsm+12Huy/rkKxVu4R1+r96YX5cG44rHV0pQ6iC3Q+mkoMFaGWObMFYQxCVT+ssG1ksneA2MI9KQ== + +fluent-ffmpeg@^2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz" + integrity sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q== + dependencies: + async ">=0.2.9" + which "^1.1.1" + +fold-to-ascii@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/fold-to-ascii/-/fold-to-ascii-5.0.1.tgz#d0b4f06e7b511e959bd502fa49e8e3678b9fc6cc" + integrity sha512-VdMFm+u7pSzUWj0IDOniuHekp4lbMOtwKi6EsVx03DGVQaNI+77kxotj8hYaMmNkpym7wwv6c1woY4OZXYdqfg== + +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + +follow-redirects@^1.14.0, follow-redirects@^1.14.4: + version "1.15.1" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz" + integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== -follow-redirects@^1.14.0: - version "1.14.2" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.2.tgz" - integrity sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA== +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" for-in@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== form-auto-content@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/form-auto-content/-/form-auto-content-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/form-auto-content/-/form-auto-content-2.2.0.tgz#8ab8d26d6315e9d592e3876053d8da5d1da4a8b1" integrity sha512-OT4qi6hNGc+fJJGieTjy+WmV1nDhg4ULATNR0Fx92YUIy9gPw8odX3z8c+IiivWITzTg8j4TcKKbsAku8l2dwQ== dependencies: form-data "^3.0.0" form-data@^2.3.1: version "2.5.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== dependencies: asynckit "^0.4.0" @@ -3876,7 +4758,7 @@ form-data@^2.3.1: form-data@^3.0.0: version "3.0.1" - resolved "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== dependencies: asynckit "^0.4.0" @@ -3884,45 +4766,45 @@ form-data@^3.0.0: mime-types "^2.1.12" formidable@^1.2.0: - version "1.2.2" - resolved "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz" - integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== + version "1.2.6" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" + integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ== forwarded@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== forwarded@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + integrity sha512-Ua9xNhH0b8pwE3yRbFfXJvfdWF0UHNCdeyb2sbi9Ul/M+r3PTdrz7Cv4SCfZRMjmzEM9PhraqfZFbGTIg3OMyA== fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + integrity sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA== dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== from@~0: version "0.1.7" resolved "https://registry.npmjs.org/from/-/from-0.1.7.tgz" - integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4= + integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g== fs-constants@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== fs-extra@^9.1.0: version "9.1.0" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== dependencies: at-least-node "^1.0.0" @@ -3932,7 +4814,7 @@ fs-extra@^9.1.0: fs-minipass@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== dependencies: minipass "^3.0.0" @@ -3940,154 +4822,203 @@ fs-minipass@^2.0.0: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@^2.1.2, fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + +functions-have-names@^1.2.2: + version "1.2.3" + resolved "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= +gauge@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz" + integrity sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q== dependencies: - aproba "^1.0.3" + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.2" console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" + has-unicode "^2.0.1" + object-assign "^4.1.1" signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.2" generate-password@^1.6.0: - version "1.6.1" - resolved "https://registry.npmjs.org/generate-password/-/generate-password-1.6.1.tgz" - integrity sha512-JvtWSiN4KVmF6kBFi89Uz9LLN7l/EuGZYiKrIxddFlKcjSgc3D3va0Z5faooNwN85O0VBlt/ZtTdqhbQKhAOyw== + version "1.7.0" + resolved "https://registry.yarnpkg.com/generate-password/-/generate-password-1.7.0.tgz#00ba4eb1e71f89a72307b0d6604ee0d4e7f5770c" + integrity sha512-WPCtlfy0jexf7W5IbwxGUgpIDvsZIohbI2DAq2Q6TSlKKis+G4GT9sxvPxrZUGL8kP6WUXMWNqYnxY6DDKAdFA== + +generic-pool@3.8.2: + version "3.8.2" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.8.2.tgz#aab4f280adb522fdfbdc5e5b64d718d3683f04e9" + integrity sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + 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, get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + version "1.1.2" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz" + integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-symbols "^1.0.3" get-package-type@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== get-stdin@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" - resolved "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== + +get-website-favicon@^0.0.7: + version "0.0.7" + resolved "https://registry.npmjs.org/get-website-favicon/-/get-website-favicon-0.0.7.tgz" + integrity sha512-FD452CzghMhdMytp09Ax5R/IAi6835DcFsbF/kXNDa5Aep+aVN+c2kmy5wDTLPtY2Tnlh4eq1j6GgXtUGK3gYQ== + dependencies: + axios "^0.18.0" + cheerio "^1.0.0-rc.2" + file-type "^7.6.0" github-from-package@0.0.0: version "0.0.0" resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: - version "7.1.7" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz" - integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + version "7.2.3" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-dirs@^2.0.1: version "2.1.0" - resolved "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" integrity sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ== dependencies: ini "1.3.7" globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globals@^13.6.0, globals@^13.9.0: - version "13.11.0" - resolved "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz" - integrity sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g== + version "13.15.0" + resolved "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== dependencies: type-fest "^0.20.2" globby@^11.0.3: - version "11.0.4" - resolved "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" +globby@^13.1.1: + version "13.1.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" + integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + gm@^1.23.1: version "1.23.1" resolved "https://registry.npmjs.org/gm/-/gm-1.23.1.tgz" - integrity sha1-Lt7rlYCE0PjqeYjl2ZWxx9/BR3c= + integrity sha512-wYGVAa8/sh9ggF5qWoOs6eArcAgwEPkDNvf637jHRHkMUznvs7m/Q2vrc0KLN6B8px3nnRJqJcXK4mTK6lLFmg== dependencies: array-parallel "~0.1.3" array-series "~0.1.5" @@ -4096,7 +5027,7 @@ gm@^1.23.1: got@^9.6.0: version "9.6.0" - resolved "https://registry.npmjs.org/got/-/got-9.6.0.tgz" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== dependencies: "@sindresorhus/is" "^0.14.0" @@ -4112,23 +5043,28 @@ got@^9.6.0: url-parse-lax "^3.0.0" graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: - version "4.2.8" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + version "4.2.10" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== growly@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + integrity sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw== -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== has-binary2@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== dependencies: isarray "2.0.1" @@ -4136,39 +5072,46 @@ has-binary2@~1.0.2: has-cors@1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz" - integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + integrity sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA== has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-tostringtag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== dependencies: has-symbols "^1.0.2" -has-unicode@^2.0.0: +has-unicode@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ== has-value@^0.3.1: version "0.3.1" resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + integrity sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q== dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -4177,7 +5120,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + integrity sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw== dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -4186,85 +5129,152 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + integrity sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ== has-values@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + integrity sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ== dependencies: is-number "^3.0.0" kind-of "^4.0.0" has-yarn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.2.0, he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hexoid@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18" integrity sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g== +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" + integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + hosted-git-info@^2.1.4: version "2.8.9" - resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + hpagent@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/hpagent/-/hpagent-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== html-encoding-sniffer@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== dependencies: whatwg-encoding "^1.0.5" html-escaper@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +html-metadata-parser@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/html-metadata-parser/-/html-metadata-parser-2.0.4.tgz" + integrity sha512-pBjST/bbe3nuy/fNmvyY4G+ypukQ/QHiGc+YnS4up2OVnT4vI0CZA4x2J0Ri77sQkQGH2IMAAug0fE78FfDrLw== + dependencies: + axios "^0.24.0" + node-html-parser "^5.2.0" + +html-to-text@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-8.2.1.tgz#4a75b8a1b646149bd71c50527adb568990bf459b" + integrity sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w== + dependencies: + "@selderee/plugin-htmlparser2" "^0.6.0" + deepmerge "^4.2.2" + he "^1.2.0" + htmlparser2 "^6.1.0" + minimist "^1.2.6" + selderee "^0.6.0" + +htmlparser2@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" + integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A== + dependencies: + domelementtype "^2.0.1" + domhandler "^4.0.0" + domutils "^2.5.2" + entities "^2.0.0" + +htmlparser2@^8.0.1: + version "8.0.1" + resolved "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz" + integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + domutils "^3.0.1" + entities "^4.3.0" + http-cache-semantics@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== -http-errors@^1.7.3, http-errors@^1.8.0: - version "1.8.0" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz" - integrity sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A== +http-errors@1.8.1, http-errors@^1.7.3, http-errors@^1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== dependencies: depd "~1.1.2" inherits "2.0.4" setprototypeof "1.2.0" statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + toidentifier "1.0.1" http-proxy-agent@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz" + 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" @@ -4272,19 +5282,19 @@ http-proxy-agent@^4.0.1: debug "4" https-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz" - integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + version "5.0.1" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" debug "4" human-signals@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -4293,27 +5303,27 @@ iconv-lite@0.4.24: ieee754@^1.1.13: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz" - integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= + integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA== ignore@^4.0.6: version "4.0.6" - resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + 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" @@ -4322,12 +5332,12 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== import-local@^3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz" - integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + version "3.1.0" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -4335,62 +5345,82 @@ import-local@^3.0.2: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" + integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== indexof@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz" - integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + integrity sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg== inflight@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@1.3.7, ini@~1.3.0: +ini@1.3.7: version "1.3.7" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + internal-slot@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" + 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" +ip@^1.1.5: + version "1.1.8" + resolved "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz" + integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== + ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +ipaddr.js@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz" + integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + integrity sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A== dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-arguments@^1.0.4: version "1.1.1" - resolved "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== dependencies: call-bind "^1.0.2" @@ -4399,30 +5429,30 @@ is-arguments@^1.0.4: is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-arrayish@^0.3.1: version "0.3.2" - resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== is-bigint@^1.0.1: version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== dependencies: has-bigints "^1.0.1" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-boolean-object@^1.1.0: version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== dependencies: call-bind "^1.0.2" @@ -4430,52 +5460,64 @@ is-boolean-object@^1.1.0: is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-callable@^1.1.4, is-callable@^1.2.3: +is-buffer@^2.0.2: + version "2.0.5" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: version "1.2.4" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== is-ci@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== dependencies: ci-info "^2.0.0" -is-core-module@^2.2.0: - version "2.6.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz" - integrity sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ== +is-core-module@^2.5.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + dependencies: + has "^1.0.3" + +is-core-module@^2.9.0: + version "2.9.0" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== dependencies: has "^1.0.3" is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + integrity sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg== dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-date-object@^1.0.1: version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== dependencies: has-tostringtag "^1.0.0" is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" @@ -4484,7 +5526,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" @@ -4493,17 +5535,17 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-docker@^2.0.0: version "2.2.1" - resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" @@ -4511,47 +5553,35 @@ is-extendable@^1.0.1: is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + 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-generator-fn@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-generator-function@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== dependencies: has-tostringtag "^1.0.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + version "4.0.3" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" is-installed-globally@^0.3.1: version "0.3.2" - resolved "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141" integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g== dependencies: global-dirs "^2.0.1" @@ -4559,63 +5589,68 @@ is-installed-globally@^0.3.1: is-interactive@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== is-npm@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + version "1.0.7" + resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== dependencies: has-tostringtag "^1.0.0" is-number@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + integrity sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg== dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-obj@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== is-path-inside@^3.0.1: version "3.0.3" - resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^1.1, is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-potential-custom-element-name@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.1.3: +is-regex@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== dependencies: call-bind "^1.0.2" @@ -4623,111 +5658,125 @@ is-regex@^1.1.3: is-retry-allowed@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== is-stream@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.5, is-string@^1.0.6: +is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== dependencies: has-tostringtag "^1.0.0" is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.3, is-typed-array@^1.1.6: - version "1.1.7" - resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.7.tgz" - integrity sha512-VxlpTBGknhQ3o7YiVjIhdLU6+oD8dPz/79vvvH4F+S/c8608UCVa9fgDpa1kZgFoUST2DCgacc70UszKgzKuvA== +is-typed-array@^1.1.3, is-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz" + integrity sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A== dependencies: - available-typed-arrays "^1.0.4" + available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" + es-abstract "^1.20.0" + for-each "^0.3.3" has-tostringtag "^1.0.0" is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-wsl@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== dependencies: is-docker "^2.0.0" is-yarn-global@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== isarray@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isarray@2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz" - integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + integrity sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^2.0.0: version "2.1.0" resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + integrity sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA== dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -istanbul-lib-coverage@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz" - integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: +istanbul-lib-instrument@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" + 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" @@ -4735,9 +5784,20 @@ istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: istanbul-lib-coverage "^3.0.0" semver "^6.3.0" +istanbul-lib-instrument@^5.0.4: + version "5.2.0" + resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz" + integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + istanbul-lib-report@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" + 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" @@ -4745,25 +5805,30 @@ istanbul-lib-report@^3.0.0: supports-color "^7.1.0" istanbul-lib-source-maps@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz" - integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + version "4.0.1" + resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== 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.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz" - integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + version "3.1.4" + resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz" + integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +iterate-object@^1.3.0, iterate-object@^1.3.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/iterate-object/-/iterate-object-1.3.4.tgz#fa50b1d9e58e340a7dd6b4c98c8a5e182e790096" + integrity sha512-4dG1D1x/7g8PwHS9aK6QV5V94+ZvyP4+d19qDv43EzImmrndysIl4prmJ1hWWIGCqrZHyaHBm6BSEWHOLnpoNw== + jest-changed-files@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== dependencies: "@jest/types" "^26.6.2" @@ -4772,7 +5837,7 @@ jest-changed-files@^26.6.2: jest-cli@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== dependencies: "@jest/core" "^26.6.3" @@ -4791,7 +5856,7 @@ jest-cli@^26.6.3: jest-config@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== dependencies: "@babel/core" "^7.1.0" @@ -4815,7 +5880,7 @@ jest-config@^26.6.3: jest-diff@^26.0.0, jest-diff@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== dependencies: chalk "^4.0.0" @@ -4825,14 +5890,14 @@ jest-diff@^26.0.0, jest-diff@^26.6.2: jest-docblock@^26.0.0: version "26.0.0" - resolved "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== dependencies: detect-newline "^3.0.0" jest-each@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== dependencies: "@jest/types" "^26.6.2" @@ -4843,7 +5908,7 @@ jest-each@^26.6.2: jest-environment-jsdom@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== dependencies: "@jest/environment" "^26.6.2" @@ -4856,7 +5921,7 @@ jest-environment-jsdom@^26.6.2: jest-environment-node@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== dependencies: "@jest/environment" "^26.6.2" @@ -4868,12 +5933,12 @@ jest-environment-node@^26.6.2: jest-get-type@^26.3.0: version "26.3.0" - resolved "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== jest-haste-map@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== dependencies: "@jest/types" "^26.6.2" @@ -4894,7 +5959,7 @@ jest-haste-map@^26.6.2: jest-jasmine2@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== dependencies: "@babel/traverse" "^7.1.0" @@ -4918,7 +5983,7 @@ jest-jasmine2@^26.6.3: jest-leak-detector@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== dependencies: jest-get-type "^26.3.0" @@ -4926,7 +5991,7 @@ jest-leak-detector@^26.6.2: jest-matcher-utils@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== dependencies: chalk "^4.0.0" @@ -4936,7 +6001,7 @@ jest-matcher-utils@^26.6.2: jest-message-util@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== dependencies: "@babel/code-frame" "^7.0.0" @@ -4951,7 +6016,7 @@ jest-message-util@^26.6.2: jest-mock@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== dependencies: "@jest/types" "^26.6.2" @@ -4959,17 +6024,17 @@ jest-mock@^26.6.2: jest-pnp-resolver@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== jest-regex-util@^26.0.0: version "26.0.0" - resolved "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== jest-resolve-dependencies@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== dependencies: "@jest/types" "^26.6.2" @@ -4978,7 +6043,7 @@ jest-resolve-dependencies@^26.6.3: jest-resolve@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== dependencies: "@jest/types" "^26.6.2" @@ -4992,7 +6057,7 @@ jest-resolve@^26.6.2: jest-runner@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== dependencies: "@jest/console" "^26.6.2" @@ -5018,7 +6083,7 @@ jest-runner@^26.6.3: jest-runtime@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== dependencies: "@jest/console" "^26.6.2" @@ -5051,7 +6116,7 @@ jest-runtime@^26.6.3: jest-serializer@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== dependencies: "@types/node" "*" @@ -5059,7 +6124,7 @@ jest-serializer@^26.6.2: jest-snapshot@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== dependencies: "@babel/types" "^7.0.0" @@ -5081,7 +6146,7 @@ jest-snapshot@^26.6.2: jest-util@^26.1.0, jest-util@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== dependencies: "@jest/types" "^26.6.2" @@ -5093,7 +6158,7 @@ jest-util@^26.1.0, jest-util@^26.6.2: jest-validate@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== dependencies: "@jest/types" "^26.6.2" @@ -5105,7 +6170,7 @@ jest-validate@^26.6.2: jest-watcher@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== dependencies: "@jest/test-result" "^26.6.2" @@ -5118,7 +6183,7 @@ jest-watcher@^26.6.2: jest-worker@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" @@ -5127,7 +6192,7 @@ jest-worker@^26.6.2: jest@^26.6.3: version "26.6.3" - resolved "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== dependencies: "@jest/core" "^26.6.3" @@ -5137,26 +6202,26 @@ jest@^26.6.3: jmespath@^0.15.0: version "0.15.0" resolved "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz" - integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= + integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w== join-component@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/join-component/-/join-component-1.1.0.tgz" - integrity sha1-uEF7dQZho5K+4sJTfGiyqdSXfNU= + integrity sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ== joycon@^2.2.5: version "2.2.5" - resolved "https://registry.npmjs.org/joycon/-/joycon-2.2.5.tgz" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.13.1: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" + 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" @@ -5164,14 +6229,14 @@ js-yaml@^3.13.1: js-yaml@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsdom@^16.4.0: version "16.7.0" - resolved "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw== dependencies: abab "^2.0.5" @@ -5204,27 +6269,27 @@ jsdom@^16.4.0: jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json-buffer@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== json-parse-even-better-errors@^2.3.0: version "2.3.1" - resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-resolver@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz#0840864b06780363d31fb03cdfae5047e2f81fbb" integrity sha512-EX7W1r8aZ/T3j8GbbBxPXi60bnsELfT90OiA1QrbGMvwzVSbyMNOAzvMFcFb8m7gKCXZLJpGe+cJOvWgoFl29A== dependencies: debug "^4.1.1" @@ -5233,43 +6298,46 @@ json-schema-resolver@^1.3.0: json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + 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.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + 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.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== json-stream@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/json-stream/-/json-stream-1.0.0.tgz" - integrity sha1-GjhU4o0rvuqzHMfd9oPS3cVlJwg= + integrity sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg== -json5@2.x, json5@^2.1.1, json5@^2.1.2: - version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" +json-stringify-safe@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@2.x, json5@^2.1.1, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" -jsonwebtoken@^8.3.0, jsonwebtoken@^8.5.1: +jsonwebtoken@^8.5.1: version "8.5.1" - resolved "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== dependencies: jws "^3.2.2" @@ -5283,9 +6351,14 @@ jsonwebtoken@^8.3.0, jsonwebtoken@^8.5.1: ms "^2.1.1" semver "^5.6.0" +junk@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/junk/-/junk-4.0.0.tgz#9b1104ddf5281cd24ffa3c8a7443d19ce192b37f" + integrity sha512-ojtSU++zLJ3jQG9bAYjg94w+/DOJtRyD7nPaerMFrBhmdVmiV5/exYH5t4uHga4G/95nT6hr1OJoKIFbYbrW5w== + jwa@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== dependencies: buffer-equal-constant-time "1.0.1" @@ -5294,7 +6367,7 @@ jwa@^1.4.1: jws@^3.2.2: version "3.2.2" - resolved "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== dependencies: jwa "^1.4.1" @@ -5302,7 +6375,7 @@ jws@^3.2.2: keyv@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== dependencies: json-buffer "3.0.0" @@ -5310,35 +6383,35 @@ keyv@^3.0.0: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + integrity sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw== dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -kind-of@^6.0.0, kind-of@^6.0.2: +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== kleur@^3.0.3: version "3.0.3" - resolved "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== latest-version@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA== dependencies: package-json "^6.3.0" @@ -5346,16 +6419,16 @@ latest-version@^5.0.0: leven@2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz" - integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= + integrity sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA== leven@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + 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" @@ -5364,97 +6437,98 @@ levn@^0.4.1: levn@~0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" light-my-request@^4.2.0: - version "4.4.4" - resolved "https://registry.npmjs.org/light-my-request/-/light-my-request-4.4.4.tgz" - integrity sha512-nxYLB+Lke3wGQ55HQIo/CjSS18xGyHRF0y/u7YxEwp1YsqQTxObteBXYHZY3ELSvYmqy0pRLTWbI5//zRYTXlg== + version "4.10.1" + resolved "https://registry.npmjs.org/light-my-request/-/light-my-request-4.10.1.tgz" + integrity sha512-l+zWk0HXGhGzY7IYTZnYEqIpj3Mpcyk2f8+FkKUyREywvaiWCf2jyQVxpasKRsploY/nVpoqTlxx72CIeQNcIQ== dependencies: ajv "^8.1.0" - cookie "^0.4.0" - fastify-warning "^0.2.0" - readable-stream "^3.6.0" + cookie "^0.5.0" + process-warning "^1.0.0" set-cookie-parser "^2.4.1" lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + version "1.2.4" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + 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.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" - integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz" - integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w== lodash.isboolean@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz" - integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== lodash.isinteger@^4.0.4: version "4.0.4" resolved "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz" - integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA== lodash.isnumber@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz" - integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw== lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" - integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== lodash.isstring@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz" - integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw== lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== lodash.once@^4.0.0: version "4.1.1" resolved "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz" - integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== lodash.truncate@^4.4.2: version "4.4.2" resolved "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz" - integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM= + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== lodash@4.x, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -5463,21 +6537,28 @@ log-symbols@^4.1.0: long@^2.2.0: version "2.4.0" resolved "https://registry.npmjs.org/long/-/long-2.4.0.tgz" - integrity sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8= + integrity sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ== + +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lowercase-keys@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== lru-cache@^4.0.1: version "4.1.5" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" @@ -5485,7 +6566,7 @@ lru-cache@^4.0.1: lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + 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" @@ -5493,52 +6574,78 @@ lru-cache@^6.0.0: lru_map@^0.3.3: version "0.3.3" resolved "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz" - integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= + integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== make-dir@^3.0.0, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + 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" make-error@1.x, make-error@^1.1.1: version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== dependencies: - tmpl "1.0.x" + tmpl "1.0.5" map-cache@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== + +map-o@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/map-o/-/map-o-2.0.10.tgz#b656a75cead939a936c338fb5df8c9d55f0dbb23" + integrity sha512-BxazE81fVByHWasyXhqKeo2m7bFKYu+ZbEfiuexMOnklXW+tzDvnlTi/JaklEeuuwqcqJzPaf9q+TWptSGXeLg== + dependencies: + iterate-object "^1.3.0" + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== map-stream@~0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz" - integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ= + integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g== map-visit@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + integrity sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w== dependencies: object-visit "^1.0.0" match-all@^1.2.6: version "1.2.6" - resolved "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + md5@^2.2.1: version "2.3.0" - resolved "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g== dependencies: charenc "0.0.2" @@ -5548,31 +6655,56 @@ md5@^2.2.1: media-typer@0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memory-pager@^1.0.2: version "1.5.0" - resolved "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" integrity sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg== +meow@^10.1.2: + version "10.1.3" + resolved "https://registry.yarnpkg.com/meow/-/meow-10.1.3.tgz#21689959a7d00e8901aff30d208acb2122eb8088" + integrity sha512-0WL7RMCPPdUTE00+GxJjL4d5Dm6eUbmAzxlzywJWiRUKCW093owmZ7/q74tH9VI91vxw9KJJNxAcvdpxb2G4iA== + dependencies: + "@types/minimist" "^1.2.2" + camelcase-keys "^7.0.0" + decamelize "^5.0.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.2" + read-pkg-up "^8.0.0" + redent "^4.0.0" + trim-newlines "^4.0.2" + type-fest "^1.2.2" + yargs-parser "^20.2.9" + +merge-options@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-options/-/merge-options-1.0.1.tgz#2a64b24457becd4e4dc608283247e94ce589aa32" + integrity sha512-iuPV41VWKWBIOpBsjoxjDZw8/GbSfZ2mk7N1453bwMrfzdrIk7EzBd+8UVR6rkw67th7xnk9Dytl3J+lHPdxvg== + dependencies: + is-plain-obj "^1.1" + merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== methods@^1.1.1, methods@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -5590,71 +6722,107 @@ micromatch@^3.1.4: to-regex "^3.0.2" micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.5" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + bn.js "^4.0.0" + brorand "^1.0.1" -mime-db@1.49.0: - version "1.49.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz" - integrity sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.14, mime-types@~2.1.24: - version "2.1.32" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz" - integrity sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A== +mime-types@^2.1.12, mime-types@^2.1.14, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.49.0" + mime-db "1.52.0" mime@1.6.0, mime@^1.4.1: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.4.0: - version "2.5.2" - resolved "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz" - integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== + version "2.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz" + integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== mimic-fn@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== -mimic-response@^2.0.0: - version "2.1.0" - resolved "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz" - integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +min-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" + integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minio@^7.0.18: - version "7.0.19" - resolved "https://registry.npmjs.org/minio/-/minio-7.0.19.tgz" - integrity sha512-DOGKauWLdmj0/y2QKXdnrhqyzRFEnUteHi6q382uujg9TjSDrA84BiQVppS2Ew6V8Rcg+2IaRkF4GR34zw9sIA== + version "7.0.28" + resolved "https://registry.npmjs.org/minio/-/minio-7.0.28.tgz" + integrity sha512-4Oua0R73oCxxmxhh2NiXDJo4Md159I/mdG8ybu6351leMQoB2Sy8S4HmgG6CxuPlEJ0h9M8/WyaI2CARDeeDTQ== dependencies: async "^3.1.0" block-stream2 "^2.0.0" + browser-or-node "^1.3.0" + buffer-crc32 "^0.2.13" + crypto-browserify "^3.12.0" es6-error "^4.1.1" fast-xml-parser "^3.17.5" + ipaddr.js "^2.0.1" json-stream "^1.0.0" lodash "^4.17.21" mime-types "^2.1.14" @@ -5666,15 +6834,15 @@ minio@^7.0.18: xml2js "^0.4.15" minipass@^3.0.0: - version "3.1.3" - resolved "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz" - integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + version "3.3.4" + resolved "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz" + integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== dependencies: yallist "^4.0.0" minizlib@^2.1.1: version "2.1.2" - resolved "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" @@ -5682,7 +6850,7 @@ minizlib@^2.1.1: mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" @@ -5690,80 +6858,74 @@ mixin-deep@^1.2.0: mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: version "0.5.3" - resolved "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== mkdirp@1.x, mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -moment-timezone@^0.5.31: - version "0.5.33" - resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz" - integrity sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w== + version "0.5.6" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== dependencies: - moment ">= 2.9.0" + minimist "^1.2.6" -"moment@>= 2.9.0", moment@^2.29.1: - version "2.29.1" - resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz" - integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== +moment@^2.29.4: + version "2.29.4" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" + integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== -mongodb-connection-string-url@^1.0.1: - version "1.1.2" - resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-1.1.2.tgz" - integrity sha512-mp5lv4guWuykOpkwNNqQ0tKKytuJUjL/aC/bu/DqoJVWL5NSh4j/u+gJ+EiOdweLujHyq6JZZqcTVipHhL5xRg== +mongodb-connection-string-url@^2.5.2: + version "2.5.2" + resolved "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz" + integrity sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA== dependencies: - "@types/whatwg-url" "^8.0.0" - whatwg-url "^8.4.0" + "@types/whatwg-url" "^8.2.1" + whatwg-url "^11.0.0" mongodb@*, mongodb@^4.1.0: - version "4.1.0" - resolved "https://registry.npmjs.org/mongodb/-/mongodb-4.1.0.tgz" - integrity sha512-Gx9U9MsFWgJ3E0v4oHAdWvYTGBznNYPCkhmD/3i/kPTY/URnPfHD5/6VoKUFrdgQTK3icFiM9976hVbqCRBO9Q== - dependencies: - bson "^4.4.0" - denque "^1.5.0" - mongodb-connection-string-url "^1.0.1" + version "4.7.0" + resolved "https://registry.npmjs.org/mongodb/-/mongodb-4.7.0.tgz" + integrity sha512-HhVar6hsUeMAVlIbwQwWtV36iyjKd9qdhY+s4wcU8K6TOj4Q331iiMy+FoPuxEntDIijTYWivwFJkLv8q/ZgvA== + dependencies: + bson "^4.6.3" + denque "^2.0.1" + mongodb-connection-string-url "^2.5.2" + socks "^2.6.2" optionalDependencies: - saslprep "^1.0.0" + saslprep "^1.0.3" + +moo@^0.5.0, moo@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4" + integrity sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w== mri@1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" integrity sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w== ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multistream@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/multistream/-/multistream-4.1.0.tgz#7bf00dfd119556fbc153cff3de4c6d477909f5a8" integrity sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw== dependencies: once "^1.4.0" @@ -5771,7 +6933,7 @@ multistream@^4.1.0: nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" @@ -5788,73 +6950,105 @@ nanomatch@^1.2.9: napi-build-utils@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +nearley@^2.20.1: + version "2.20.1" + resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474" + integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ== + dependencies: + commander "^2.19.0" + moo "^0.5.0" + railroad-diagrams "^1.0.0" + randexp "0.4.6" + +needle@^2.5.2: + version "2.9.1" + resolved "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz" + integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" + integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== nice-try@^1.0.4: version "1.0.5" - resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-abi@^2.21.0: - version "2.30.1" - resolved "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz" - integrity sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w== +node-abi@^3.3.0: + version "3.22.0" + resolved "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz" + integrity sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w== dependencies: - semver "^5.4.1" + semver "^7.3.5" node-addon-api@^3.1.0: version "3.2.1" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== -node-addon-api@^4.1.0: - version "4.2.0" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.2.0.tgz" - integrity sha512-eazsqzwG2lskuzBqCGPi7Ac2UgOoMz8JVOXVhTvvPDYhthvNpefx8jWD8Np7Gv+2Sz0FlPWZk0nJV0z598Wn8Q== +node-addon-api@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz" + integrity sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA== + +node-cache@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d" + integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg== + dependencies: + clone "2.x" node-cleanup@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz" - integrity sha1-esGavSl+Caf3KnFUXZUbUX5N3iw= + integrity sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw== node-cron@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz" - integrity sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA== - dependencies: - moment-timezone "^0.5.31" + version "3.0.1" + resolved "https://registry.npmjs.org/node-cron/-/node-cron-3.0.1.tgz" + integrity sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw== -node-fetch@^2.6.1, node-fetch@^2.6.5: - version "2.6.6" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== +node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-html-parser@^5.2.0: + version "5.3.3" + resolved "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.3.3.tgz" + integrity sha512-ncg1033CaX9UexbyA7e1N0aAoAYRDiV8jkTvzEnfd1GDvzFdrsXLzR4p4ik8mwLgnaKP/jyUFWDy9q3jvRT2Jw== + dependencies: + css-select "^4.2.1" + he "1.2.0" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-notifier@^8.0.0: version "8.0.2" - resolved "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.2.tgz" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== dependencies: growly "^1.3.0" @@ -5864,19 +7058,19 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.75: - version "1.1.75" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz" - integrity sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw== +node-releases@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz" + integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== node-uuid@^1.4.8: version "1.4.8" resolved "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz" - integrity sha1-sEDrCSOWivq/jTL7HxfxFn/auQc= + integrity sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA== nodemon@2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416" integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ== dependencies: chokidar "^3.2.2" @@ -5892,7 +7086,7 @@ nodemon@2.0.4: nopt@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== dependencies: abbrev "1" @@ -5900,13 +7094,13 @@ nopt@^5.0.0: nopt@~1.0.10: version "1.0.10" resolved "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz" - integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg== dependencies: abbrev "1" normalize-package-data@^2.5.0: version "2.5.0" - resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz" + 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" @@ -5914,101 +7108,108 @@ normalize-package-data@^2.5.0: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-package-data@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== normalize-url@^4.1.0: version "4.5.1" - resolved "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== notepack.io@~2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/notepack.io/-/notepack.io-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/notepack.io/-/notepack.io-2.2.0.tgz#d7ea71d1cb90094f88c6f3c8d84277c2d0cd101c" integrity sha512-9b5w3t5VSH6ZPosoYnyDONnUTF8o0UkBw7JLA6eBlYJWyGT1Q3vQa8Hmuj1/X6RYvHjjygBDgw6fJhe0JEojfw== npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== dependencies: path-key "^2.0.0" npm-run-path@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== dependencies: path-key "^3.0.0" -npmlog@^4.0.1, npmlog@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== +npmlog@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz" + integrity sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw== dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" + are-we-there-yet "^2.0.0" + console-control-strings "^1.1.0" + gauge "^3.0.0" + set-blocking "^2.0.0" -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" nwsapi@^2.2.0: - version "2.2.0" - resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + version "2.2.1" + resolved "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz" + integrity sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg== -object-assign@^4.1.0: +object-assign@^4, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-copy@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + integrity sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ== dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== +object-inspect@^1.12.0, object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + integrity sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA== dependencies: isobject "^3.0.0" object.assign@^4.1.0, object.assign@^4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" + 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" @@ -6019,39 +7220,39 @@ object.assign@^4.1.0, object.assign@^4.1.2: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + integrity sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ== dependencies: isobject "^3.0.1" on-finished@~2.3.0: version "2.3.0" resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== dependencies: ee-first "1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" onetime@^5.1.0: version "5.1.2" - resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" -openapi-types@^9.1.0: - version "9.2.0" - resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-9.2.0.tgz" - integrity sha512-3x0gg8DxhpZ5MVki7AK6jmMdVIZASmVGo9CoUtD+nksLdkqz7EzWKdfS9Oxxq1J7idnZV0b3LjqcvizfKFySpQ== +openapi-types@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/openapi-types/-/openapi-types-10.0.0.tgz" + integrity sha512-Y8xOCT2eiKGYDzMW9R4x5cmfc3vGaaI4EL2pwhDmodWw1HlK18YcZ4uJxc7Rdp7/gGzAygzH9SXr6GKYIXbRcQ== optionator@^0.8.1: version "0.8.3" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== dependencies: deep-is "~0.1.3" @@ -6063,7 +7264,7 @@ optionator@^0.8.1: optionator@^0.9.1: version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: deep-is "^0.1.3" @@ -6075,7 +7276,7 @@ optionator@^0.9.1: ora@^5.4.0: version "5.4.1" - resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== dependencies: bl "^4.1.0" @@ -6090,41 +7291,83 @@ ora@^5.4.0: p-cancelable@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== -p-each-series@^2.1.0: - version "2.2.0" - resolved "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz" - integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== +p-each-series@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== + +p-event@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + +p-filter@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-3.0.0.tgz#ce50e03b24b23930e11679ab8694bd09a2d7ed35" + integrity sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg== + dependencies: + p-map "^5.1.0" p-finally@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + 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-limit@^3.0.2, p-limit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + 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-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^5.1.0, p-map@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-5.5.0.tgz#054ca8ca778dfa4cf3f8db6638ccb5b937266715" + integrity sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg== + dependencies: + aggregate-error "^4.0.0" + +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-json@^6.3.0: version "6.5.0" - resolved "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ== dependencies: got "^9.6.0" @@ -6134,14 +7377,25 @@ package-json@^6.3.0: parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + 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@^5.0.0: +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-json@^5.0.0, parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -6149,84 +7403,123 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + parse5@6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz" + integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g== + dependencies: + entities "^4.3.0" + +parseley@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/parseley/-/parseley-0.7.0.tgz#9949e3a0ed05c5072adb04f013c2810cf49171a8" + integrity sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw== + dependencies: + moo "^0.5.1" + nearley "^2.20.1" + parseqs@0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz" + resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.6.tgz#8e4bb5a19d1cdc844a08ac974d34e273afa670d5" integrity sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w== parseuri@0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz" + resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.6.tgz#e1496e829e3ac2ff47f39a4dd044b32823c4a25a" integrity sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow== pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + 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.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pathval@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== pause-stream@0.0.11: version "0.0.11" resolved "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz" - integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU= + integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A== dependencies: through "~2.3" +pbkdf2@^3.0.3: + version "3.1.2" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + pdf2pic@^2.1.4: version "2.1.4" - resolved "https://registry.npmjs.org/pdf2pic/-/pdf2pic-2.1.4.tgz" + resolved "https://registry.yarnpkg.com/pdf2pic/-/pdf2pic-2.1.4.tgz#5c6cbd7809a60b11f6504eb85c386aa2012b1dcf" integrity sha512-8QOCvxZlYs7wsmBQbqpIApSWD/eqgXMQU+4VM0vWrXifLgXS+Ns3484sUa1Q7ddr+gwnruq/xKHzu7x1scqX6w== dependencies: fs-extra "^9.1.0" gm "^1.23.1" -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pino-pretty@^4.7.1: version "4.8.0" - resolved "https://registry.npmjs.org/pino-pretty/-/pino-pretty-4.8.0.tgz" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-4.8.0.tgz#f2f3055bf222456217b14ffb04d8be0a0cc17fce" integrity sha512-mhQfHG4rw5ZFpWL44m0Utjo4GC2+HMfdNvxyA8lLw0sIqn6fCf7uQe6dPckUcW/obly+OQHD7B/MTso6LNizYw== dependencies: "@hapi/bourne" "^2.0.0" @@ -6244,32 +7537,30 @@ pino-pretty@^4.7.1: pino-std-serializers@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-3.2.0.tgz#b56487c402d882eb96cd67c257868016b61ad671" integrity sha512-EqX4pwDPrt3MuOAAUBMU0Tk5kR/YcCM5fNPEzgCO2zJ5HfX0vbiH9HbJglnyeQsN96Kznae6MWD47pZB5avTrg== pino@^6.13.0, pino@^6.8.0: - version "6.13.1" - resolved "https://registry.npmjs.org/pino/-/pino-6.13.1.tgz" - integrity sha512-QQf67BU+cANnc/2U+wzUV20UjO5oBryWpnNyKshdLfT9BdeiXlh9wxLGmOjAuBWMYITdMs+BtJSQQNlGRNbWpA== + version "6.14.0" + resolved "https://registry.npmjs.org/pino/-/pino-6.14.0.tgz" + integrity sha512-iuhEDel3Z3hF9Jfe44DPXR8l07bhjuFY3GMHIXbjnY9XcafbyDDwl2sN2vw2GjMPf5Nkoe+OFao7ffn9SXaKDg== dependencies: fast-redact "^3.0.0" fast-safe-stringify "^2.0.8" - fastify-warning "^0.2.0" flatstr "^1.0.12" pino-std-serializers "^3.1.0" + process-warning "^1.0.0" quick-format-unescaped "^4.0.3" sonic-boom "^1.0.2" pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" + version "4.0.5" + resolved "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + 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" @@ -6277,57 +7568,56 @@ pkg-dir@^4.2.0: posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== -prebuild-install@^6.1.4: - version "6.1.4" - resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz" - integrity sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ== +prebuild-install@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz" + integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== dependencies: - detect-libc "^1.0.3" + detect-libc "^2.0.0" expand-template "^2.0.3" github-from-package "0.0.0" minimist "^1.2.3" mkdirp-classic "^0.5.3" napi-build-utils "^1.0.1" - node-abi "^2.21.0" - npmlog "^4.0.1" + node-abi "^3.3.0" pump "^3.0.0" rc "^1.2.7" - simple-get "^3.0.3" + simple-get "^4.0.0" tar-fs "^2.0.0" tunnel-agent "^0.6.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz" + 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.1.2: - version "2.3.2" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz" - integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== + version "2.7.1" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== pretty-format@^26.0.0, pretty-format@^26.6.2: version "26.6.2" - resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== dependencies: "@jest/types" "^26.6.2" @@ -6335,32 +7625,46 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +probe-image-size@^7.2.3: + version "7.2.3" + resolved "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz" + integrity sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w== + dependencies: + lodash.merge "^4.6.2" + needle "^2.5.2" + stream-parser "~0.3.1" + process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + 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-warning@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616" + integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q== + progress@^2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== promise-breaker@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/promise-breaker/-/promise-breaker-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/promise-breaker/-/promise-breaker-5.0.0.tgz#58e8541f1619554057da95a211794d7834d30c1d" integrity sha512-mgsWQuG4kJ1dtO6e/QlNDLFtMkMzzecsC69aI5hlLEjGHFNpHrvGhFi4LiK5jg2SMQj74/diH+wZliL9LpGsyA== prompts@^2.0.1: - version "2.4.1" - resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz" - integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== + version "2.4.2" + resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== dependencies: kleur "^3.0.3" sisteransi "^1.0.5" proxy-addr@^2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" @@ -6368,7 +7672,7 @@ proxy-addr@^2.0.7: ps-tree@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd" integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA== dependencies: event-stream "=3.3.4" @@ -6376,21 +7680,33 @@ ps-tree@^1.2.0: pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== psl@^1.1.33: - version "1.8.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pstree.remy@^1.1.7: version "1.1.8" - resolved "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz" + resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a" integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + pump@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" + 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" @@ -6398,51 +7714,103 @@ pump@^3.0.0: punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== pupa@^2.0.1: version "2.1.1" - resolved "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62" integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A== dependencies: escape-goat "^2.0.0" qs@^6.5.1: - version "6.10.1" - resolved "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz" - integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + version "6.11.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== dependencies: side-channel "^1.0.4" querystring@0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== querystringify@^2.1.1: version "2.2.0" - resolved "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== queue-microtask@^1.1.2, queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== quick-format-unescaped@^4.0.3: - version "4.0.3" - resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz" - integrity sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg== + version "4.0.4" + resolved "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + +railroad-diagrams@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" + integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A== + +randexp@0.4.6: + version "0.4.6" + resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" + integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== + dependencies: + discontinuous-range "1.0.0" + ret "~0.1.10" + +random-bytes@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" + integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== + +random-seed@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/random-seed/-/random-seed-0.3.0.tgz#d945f2e1f38f49e8d58913431b8bf6bb937556cd" + integrity sha512-y13xtn3kcTlLub3HKWXxJNeC2qK4mB59evwZ5EkeRlolx+Bp2ztF7LbcZmyCnOqlHQrLnfuNbi1sVmm9lPDlDA== + dependencies: + json-stringify-safe "^5.0.1" + +random-useragent@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/random-useragent/-/random-useragent-0.5.0.tgz#83a92dfdfb2366972d0a1f81fc93d5ef85807ae8" + integrity sha512-FUMkqVdZeoSff5tErNL3FFGYXElDWZ1bEuedhm5u9MdCFwANriJWbHvDRYrLTOzp/fBsBGu5J1cWtDgifa97aQ== + dependencies: + random-seed "^0.3.0" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc@^1.2.7, rc@^1.2.8: +rc@1.2.8, rc@^1.2.7, rc@^1.2.8: version "1.2.8" - resolved "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" @@ -6452,21 +7820,30 @@ rc@^1.2.7, rc@^1.2.8: react-is@^17.0.1: version "17.0.2" - resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== read-pkg-up@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== dependencies: find-up "^4.1.0" read-pkg "^5.2.0" type-fest "^0.8.1" +read-pkg-up@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-8.0.0.tgz#72f595b65e66110f43b052dd9af4de6b10534670" + integrity sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ== + dependencies: + find-up "^5.0.0" + read-pkg "^6.0.0" + type-fest "^1.0.1" + read-pkg@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== dependencies: "@types/normalize-package-data" "^2.4.0" @@ -6474,10 +7851,20 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +read-pkg@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-6.0.0.tgz#a67a7d6a1c2b0c3cd6aa2ea521f40c458a4a504c" + integrity sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^3.0.2" + parse-json "^5.2.0" + type-fest "^1.0.1" + "readable-stream@1.x >=1.1.9": version "1.1.14" resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + integrity sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ== dependencies: core-util-is "~1.0.0" inherits "~2.0.1" @@ -6486,16 +7873,16 @@ read-pkg@^5.2.0: "readable-stream@2 || 3", readable-stream@^3.0.0, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.6, readable-stream@^2.3.5: +readable-stream@^2.3.5: version "2.3.7" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" + 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" @@ -6508,31 +7895,51 @@ readable-stream@^2.0.6, readable-stream@^2.3.5: readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" +redent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-4.0.0.tgz#0c0ba7caabb24257ab3bb7a4fd95dd1d5c5681f9" + integrity sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag== + dependencies: + indent-string "^5.0.0" + strip-indent "^4.0.0" + redis-commands@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ== redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz" - integrity sha1-62LSrbFeTq9GEMBK/hUpOEJQq60= + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== redis-parser@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz" - integrity sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ= + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== dependencies: redis-errors "^1.0.0" -redis@^3.0.0: +redis@*: + version "4.2.0" + resolved "https://registry.yarnpkg.com/redis/-/redis-4.2.0.tgz#1278a265b8aa1e096a585d103bdead027cd04e43" + integrity sha512-bCR0gKVhIXFg8zCQjXEANzgI01DDixtPZgIUZHBCmwqixnu+MK3Tb2yqGjh+HCLASQVVgApiwhNkv+FoedZOGQ== + dependencies: + "@redis/bloom" "1.0.2" + "@redis/client" "1.2.0" + "@redis/graph" "1.0.1" + "@redis/json" "1.0.3" + "@redis/search" "1.0.6" + "@redis/time-series" "1.0.3" + +redis@3: version "3.1.2" - resolved "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/redis/-/redis-3.1.2.tgz#766851117e80653d23e0ed536254677ab647638c" integrity sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw== dependencies: denque "^1.5.0" @@ -6542,164 +7949,174 @@ redis@^3.0.0: reflect-metadata@^0.1.13: version "0.1.13" - resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== +regenerate-unicode-properties@^10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz" + integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw== dependencies: - regenerate "^1.4.0" + regenerate "^1.4.2" -regenerate@^1.4.0: +regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: version "0.13.9" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== +regenerator-transform@^0.15.0: + version "0.15.0" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz" + integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.4.3: + version "1.4.3" + resolved "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz" + integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + functions-have-names "^1.2.2" + regexpp@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^4.7.1: - version "4.7.1" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== +regexpu-core@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz" + integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA== dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.0.1" + regjsgen "^0.6.0" + regjsparser "^0.8.2" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.0.0" registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw== dependencies: rc "^1.2.8" -regjsgen@^0.5.1: - version "0.5.2" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== +regjsgen@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz" + integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA== -regjsparser@^0.6.4: - version "0.6.9" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz" - integrity sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ== +regjsparser@^0.8.2: + version "0.8.4" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz" + integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA== dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + integrity sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw== remove-trailing-slash@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz" + resolved "https://registry.yarnpkg.com/remove-trailing-slash/-/remove-trailing-slash-0.1.1.tgz#be2285a59f39c74d1bce4f825950061915e3780d" integrity sha512-o4S4Qh6L2jpnCy83ysZDau+VORNvnFw07CKSAymkd6ICNVEPisMyzlc00KlvvicsxKck94SEwhDnMNdICzO+tA== repeat-element@^1.1.2: version "1.1.4" - resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== require-directory@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" + 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.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== requires-port@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + 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.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== resolve@^1.0.0, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.18.1: - version "1.20.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.1" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" responselike@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + integrity sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ== dependencies: lowercase-keys "^1.0.0" restore-cursor@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== dependencies: onetime "^5.1.0" @@ -6707,70 +8124,78 @@ restore-cursor@^3.1.0: ret@~0.1.10: version "0.1.15" - resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== ret@~0.2.0: version "0.2.2" - resolved "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c" integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ== reusify@^1.0.0, reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== rimraf@^2.6.1: version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + rsvp@^4.8.4: version "4.8.5" - resolved "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" rxjs@^6.6.3: version "6.6.7" - resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0, safe-buffer@~5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1, safe-buffer@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0, safe-buffer@~5.2.1: - version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - safe-regex2@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9" integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ== dependencies: ret "~0.2.0" @@ -6778,18 +8203,18 @@ safe-regex2@^2.0.0: safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + integrity sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg== dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sane@^4.0.3: version "4.1.0" - resolved "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== dependencies: "@cnakazawa/watch" "^1.0.3" @@ -6802,68 +8227,75 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" -saslprep@^1.0.0: +saslprep@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== dependencies: sparse-bitfield "^3.0.3" -sax@>=0.6.0: +sax@>=0.6.0, sax@^1.2.4: version "1.2.4" - resolved "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== saxes@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== dependencies: xmlchars "^2.2.0" secure-json-parse@^2.0.0, secure-json-parse@^2.4.0: - version "2.4.0" - resolved "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz" - integrity sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg== + version "2.5.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.5.0.tgz#f929829df2adc7ccfb53703569894d051493a6ac" + integrity sha512-ZQruFgZnIWH+WyO9t5rWt4ZEGqCKPwhiw+YbzTwpmT9elgLrLcfuyUiSnwwjUiVy9r4VM3urtbNF1xmEh9IL2w== + +selderee@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/selderee/-/selderee-0.6.0.tgz#f3bee66cfebcb6f33df98e4a1df77388b42a96f7" + integrity sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg== + dependencies: + parseley "^0.7.0" semver-diff@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg== dependencies: semver "^6.3.0" semver-store@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/semver-store/-/semver-store-0.3.0.tgz#ce602ff07df37080ec9f4fb40b29576547befbe9" integrity sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg== -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.x, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@7.x, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: + version "7.3.7" + resolved "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== send@^0.17.1: - version "0.17.1" - resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + version "0.17.2" + resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== dependencies: debug "2.6.9" depd "~1.1.2" @@ -6872,26 +8304,26 @@ send@^0.17.1: escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "1.8.1" mime "1.6.0" - ms "2.1.1" + ms "2.1.3" on-finished "~2.3.0" range-parser "~1.2.1" statuses "~1.5.0" -set-blocking@^2.0.0, set-blocking@~2.0.0: +set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== set-cookie-parser@^2.4.1: - version "2.4.8" - resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz" - integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== + version "2.5.0" + resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.0.tgz" + integrity sha512-cHMAtSXilfyBePduZEBVPTCftTQWz6ehWJD5YNUg4mqvRosrrjKbo4WS8JkB0/RxonMoohHm7cOGH60mDkRQ9w== set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" @@ -6899,40 +8331,43 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sharp@^0.29.0: - version "0.29.1" - resolved "https://registry.npmjs.org/sharp/-/sharp-0.29.1.tgz" - integrity sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ== +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: - color "^4.0.1" - detect-libc "^1.0.3" - node-addon-api "^4.1.0" - prebuild-install "^6.1.4" - semver "^7.3.5" - simple-get "^3.1.0" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sharp@^0.30.5: + version "0.30.7" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.7.tgz#7862bda98804fdd1f0d5659c85e3324b90d94c7c" + integrity sha512-G+MY2YW33jgflKPTXXptVO28HvNOo9G3j0MybYAHeEmby+QuD2U98dT6ueht9cv/XDqZspSpIhoSW+BAKJ7Hig== + dependencies: + color "^4.2.3" + detect-libc "^2.0.1" + node-addon-api "^5.0.0" + prebuild-install "^7.1.1" + semver "^7.3.7" + simple-get "^4.0.1" tar-fs "^2.1.1" tunnel-agent "^0.6.0" shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== dependencies: shebang-regex "^1.0.0" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + 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" @@ -6940,21 +8375,21 @@ shebang-command@^2.0.0: shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== shellwords@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== dependencies: call-bind "^1.0.0" @@ -6962,53 +8397,63 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + version "3.0.7" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-concat@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== -simple-get@^3.0.3, simple-get@^3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== +simple-get@^4.0.0, simple-get@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== dependencies: - decompress-response "^4.2.0" + decompress-response "^6.0.0" once "^1.3.1" simple-concat "^1.0.0" simple-swizzle@^0.2.2: version "0.2.2" resolved "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz" - integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== dependencies: is-arrayish "^0.3.1" sisteransi@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + slice-ansi@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz" + 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" +smart-buffer@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz" + integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== + snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" @@ -7017,14 +8462,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" @@ -7036,15 +8481,15 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-adapter@~1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz" - integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== - -socket.io-client@2.4.0, socket.io-client@^2.3.1: +socket.io-adapter@^2.4.0, socket.io-adapter@~2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz" - integrity sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ== + resolved "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz" + integrity sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg== + +socket.io-client@^2.3.1: + version "2.5.0" + resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz" + integrity sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw== dependencies: backo2 "1.0.2" component-bind "1.0.0" @@ -7059,81 +8504,69 @@ socket.io-client@2.4.0, socket.io-client@^2.3.1: to-array "0.1.4" socket.io-parser@*: - version "4.0.4" - resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz" - integrity sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g== + version "4.2.1" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz" + integrity sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g== dependencies: - "@types/component-emitter" "^1.2.10" - component-emitter "~1.3.0" + "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" socket.io-parser@~3.3.0: version "3.3.2" - resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.3.2.tgz#ef872009d0adcf704f2fbe830191a14752ad50b6" integrity sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg== dependencies: component-emitter "~1.3.0" debug "~3.1.0" isarray "2.0.1" -socket.io-parser@~3.4.0: - version "3.4.1" - resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz" - integrity sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A== - dependencies: - component-emitter "1.2.1" - debug "~4.1.0" - isarray "2.0.1" - -socket.io-redis@^5.4.0: - version "5.4.0" - resolved "https://registry.npmjs.org/socket.io-redis/-/socket.io-redis-5.4.0.tgz" - integrity sha512-yCQm/Sywd3d08WXUfZRxt6O+JV2vWoPgWK6GVjiM0GkBtq5cpLOk8oILRPKbzTv1VEtSYmK41q0xzcgDinMbmQ== +socket.io-parser@~4.0.4: + version "4.0.5" + resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz" + integrity sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig== dependencies: - debug "~4.1.0" - notepack.io "~2.2.0" - redis "^3.0.0" - socket.io-adapter "~1.1.0" - uid2 "0.0.3" + "@types/component-emitter" "^1.2.10" + component-emitter "~1.3.0" + debug "~4.3.1" -socket.io@^2.3.0: - version "2.4.1" - resolved "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz" - integrity sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w== +socket.io@4: + version "4.5.1" + resolved "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz" + integrity sha512-0y9pnIso5a9i+lJmsCdtmTTgJFFSvNQKDnPQRz28mGNnxbmqYg2QPtJTLFxhymFZhAIn50eHAKzJeiNaKr+yUQ== dependencies: - debug "~4.1.0" - engine.io "~3.5.0" - has-binary2 "~1.0.2" - socket.io-adapter "~1.1.0" - socket.io-client "2.4.0" - socket.io-parser "~3.4.0" + accepts "~1.3.4" + base64id "~2.0.0" + debug "~4.3.2" + engine.io "~6.2.0" + socket.io-adapter "~2.4.0" + socket.io-parser "~4.0.4" -socketio-jwt@^4.6.2: - version "4.6.2" - resolved "https://registry.npmjs.org/socketio-jwt/-/socketio-jwt-4.6.2.tgz" - integrity sha512-bcCnit/cCvqtC921Gwuqor+LpLKrpREmPACVgLfdbFBL95w2nPF7lOxsOxyeRrhc5Kot/1jUSW5+kLo23zJIMA== +socks@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz" + integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== dependencies: - jsonwebtoken "^8.3.0" - xtend "~2.1.2" + ip "^1.1.5" + smart-buffer "^4.2.0" sonic-boom@^1.0.2: version "1.4.1" - resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.4.1.tgz#d35d6a74076624f12e6f917ade7b9d75e918f53e" integrity sha512-LRHh/A8tpW7ru89lrlkU4AszXt1dbwSjVWguGrmlxE7tawVmDBlI1PILMkXAxJTwqhgsEeTHzj36D5CmHgQmNg== dependencies: atomic-sleep "^1.0.0" flatstr "^1.0.12" sonic-boom@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.1.0.tgz" - integrity sha512-x2j9LXx27EDlyZEC32gBM+scNVMdPutU7FIKV2BOTKCnPrp7bY5BsplCMQ4shYYR3IhDSIrEXoqb6GlS+z7KyQ== + version "2.8.0" + resolved "https://registry.npmjs.org/sonic-boom/-/sonic-boom-2.8.0.tgz" + integrity sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg== dependencies: atomic-sleep "^1.0.0" source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" @@ -7143,43 +8576,43 @@ source-map-resolve@^0.5.0: urix "^0.1.0" source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5.6: - version "0.5.19" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + version "0.5.21" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map-url@^0.4.0: version "0.4.1" - resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== -source-map@^0.5.0, source-map@^0.5.6: +source-map@^0.5.6: version "0.5.7" resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + version "0.7.4" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== sparse-bitfield@^3.0.3: version "3.0.3" resolved "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz" - integrity sha1-/0rm5oZWBWuks+eSqzM004JzyhE= + integrity sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ== dependencies: memory-pager "^1.0.2" spdx-correct@^3.0.0: version "3.1.1" - resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" @@ -7187,32 +8620,32 @@ spdx-correct@^3.0.0: spdx-exceptions@^2.1.0: version "2.3.0" - resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz" + 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.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz" + 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.10" - resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz" - integrity sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA== + version "3.0.11" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" split2@^3.1.1: version "3.2.2" - resolved "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz" + resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" integrity sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg== dependencies: readable-stream "^3.0.0" @@ -7220,26 +8653,26 @@ split2@^3.1.1: split@0.3: version "0.3.3" resolved "https://registry.npmjs.org/split/-/split-0.3.3.tgz" - integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8= + integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA== dependencies: through "2" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stack-utils@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz" - integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== + version "2.0.5" + resolved "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== dependencies: escape-string-regexp "^2.0.0" static-extend@^0.1.1: version "0.1.2" resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + integrity sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g== dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -7247,12 +8680,12 @@ static-extend@^0.1.1: "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== steed@^1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/steed/-/steed-1.1.3.tgz" - integrity sha1-8VJd1a2xLrIb90dJU3Zo1iW5q8U= + integrity sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA== dependencies: fastfall "^1.5.0" fastparallel "^2.2.0" @@ -7263,28 +8696,30 @@ steed@^1.1.3: stream-combiner@~0.0.4: version "0.0.4" resolved "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz" - integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ= + integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw== dependencies: duplexer "~0.1.1" +stream-parser@~0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz" + integrity sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ== + dependencies: + debug "2" + stream-wormhole@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz" + resolved "https://registry.yarnpkg.com/stream-wormhole/-/stream-wormhole-1.1.0.tgz#300aff46ced553cfec642a05251885417693c33d" integrity sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew== -streamsearch@0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz" - integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= - string-argv@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.1.2.tgz#c5b7bc03fb2b11983ba3a72333dd0559e77e4738" integrity sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA== string-length@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== dependencies: char-regex "^1.0.2" @@ -7292,55 +8727,39 @@ string-length@^4.0.1: string-similarity@^4.0.1: version "4.0.4" - resolved "https://registry.npmjs.org/string-similarity/-/string-similarity-4.0.4.tgz" + resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== -string-width@^1.0.1, "string-width@^1.0.2 || 2": - version "1.0.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" + strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== +string.prototype.trimend@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz" + integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string.prototype.trimstart@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz" + integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" + define-properties "^1.1.4" + es-abstract "^1.19.5" string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" @@ -7348,69 +8767,67 @@ string_decoder@^1.1.1: string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + 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@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^5.1.0: - version "5.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: - ansi-regex "^5.0.0" + ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== strip-bom@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== strip-final-newline@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-4.0.0.tgz#b41379433dd06f5eae805e21d631e07ee670d853" + integrity sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA== + dependencies: + min-indent "^1.0.1" + strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.4: + version "1.0.5" + resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + superagent@^3.8.3: version "3.8.3" - resolved "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== dependencies: component-emitter "^1.2.0" @@ -7426,7 +8843,7 @@ superagent@^3.8.3: supertest@4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-4.0.2.tgz#c2234dbdd6dc79b6f15b99c8d6577b90e4ce3f36" integrity sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ== dependencies: methods "^1.1.2" @@ -7434,46 +8851,50 @@ supertest@4.0.2: supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + 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.0.0, supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + 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" supports-hyperlinks@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== dependencies: has-flag "^4.0.0" supports-color "^7.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + symbol-tree@^3.2.4: version "3.2.4" - resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^6.0.9: - version "6.7.1" - resolved "https://registry.npmjs.org/table/-/table-6.7.1.tgz" - integrity sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg== + version "6.8.0" + resolved "https://registry.npmjs.org/table/-/table-6.8.0.tgz" + integrity sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA== dependencies: ajv "^8.0.1" - lodash.clonedeep "^4.5.0" lodash.truncate "^4.4.2" slice-ansi "^4.0.0" - string-width "^4.2.0" - strip-ansi "^6.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" tar-fs@^2.0.0, tar-fs@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng== dependencies: chownr "^1.1.1" @@ -7483,7 +8904,7 @@ tar-fs@^2.0.0, tar-fs@^2.1.1: tar-stream@^2.1.4: version "2.2.0" - resolved "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== dependencies: bl "^4.0.3" @@ -7492,10 +8913,10 @@ tar-stream@^2.1.4: inherits "^2.0.3" readable-stream "^3.1.1" -tar@^6.1.0: - version "6.1.10" - resolved "https://registry.npmjs.org/tar/-/tar-6.1.10.tgz" - integrity sha512-kvvfiVvjGMxeUNB6MyYv5z7vhfFRwbwCXJAeL0/lnbrttBVqcMOnpHUf0X42LrPMR8mMpgapkJMchFH4FSHzNA== +tar@^6.1.11: + version "6.1.11" + resolved "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz" + integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" @@ -7506,12 +8927,12 @@ tar@^6.1.0: term-size@^2.1.0: version "2.2.1" - resolved "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== terminal-link@^2.0.0: version "2.1.1" - resolved "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== dependencies: ansi-escapes "^4.2.1" @@ -7519,26 +8940,31 @@ terminal-link@^2.0.0: test-exclude@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" + 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-decoding@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-decoding/-/text-decoding-1.0.0.tgz#38a5692d23b5c2b12942d6e245599cb58b1bc52f" + integrity sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== throat@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== through2@^3.0.1: version "3.0.2" - resolved "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: inherits "^2.0.4" @@ -7547,58 +8973,63 @@ through2@^3.0.1: through@2, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -tiny-lru@^7.0.0: +tiny-lru@^7.0.6: version "7.0.6" - resolved "https://registry.npmjs.org/tiny-lru/-/tiny-lru-7.0.6.tgz" + resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24" integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow== -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= +tiny-lru@^8.0.1: + version "8.0.2" + resolved "https://registry.npmjs.org/tiny-lru/-/tiny-lru-8.0.2.tgz" + integrity sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg== + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-array@0.1.4: version "0.1.4" resolved "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz" - integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + integrity sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A== to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + integrity sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg== dependencies: kind-of "^3.0.2" to-readable-stream@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + integrity sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg== dependencies: is-number "^3.0.0" repeat-string "^1.6.1" to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" @@ -7606,21 +9037,21 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== touch@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== dependencies: nopt "~1.0.10" tough-cookie@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== dependencies: psl "^1.1.33" @@ -7629,24 +9060,36 @@ tough-cookie@^4.0.0: tr46@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240" integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw== dependencies: punycode "^2.1.1" +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tree-kill@^1.2.2: version "1.2.2" - resolved "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== +trim-newlines@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-4.0.2.tgz#d6aaaf6a0df1b4b536d183879a6b939489808c7c" + integrity sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew== + ts-jest@^26.4.0: version "26.5.6" - resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.6.tgz" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.5.6.tgz#c32e0746425274e1dfe333f43cd3c800e014ec35" integrity sha512-rua+rCP8DxpA8b4DQD/6X2HQS8Zy/xzViVYfEs2OQu68tkCuKLV0Md8pmX55+W24uRIyAsf/BajRfxOs+R2MKA== dependencies: bs-logger "0.x" @@ -7662,7 +9105,7 @@ ts-jest@^26.4.0: ts-node-dev@^1.1.8: version "1.1.8" - resolved "https://registry.npmjs.org/ts-node-dev/-/ts-node-dev-1.1.8.tgz" + resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-1.1.8.tgz#95520d8ab9d45fffa854d6668e2f8f9286241066" integrity sha512-Q/m3vEwzYwLZKmV6/0VlFxcZzVV/xcgOt+Tx/VjaaRHyiBcFlV0541yrT09QjzzCxlDZ34OzKjrFAynlmtflEg== dependencies: chokidar "^3.5.1" @@ -7678,7 +9121,7 @@ ts-node-dev@^1.1.8: ts-node@^9.0.0: version "9.1.1" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" integrity sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg== dependencies: arg "^4.1.0" @@ -7689,9 +9132,9 @@ ts-node@^9.0.0: yn "3.1.1" tsc-watch@^4.2.9: - version "4.5.0" - resolved "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.5.0.tgz" - integrity sha512-aXhN4jY+1YEcn/NwCQ/+fHqU43EqOpW+pS+933EPsVEsrKhvyrodPDIjQsk1a1niFrabAK3RIBrRbAslVefEbQ== + version "4.6.2" + resolved "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.6.2.tgz" + integrity sha512-eHWzZGkPmzXVGQKbqQgf3BFpGiZZw1jQ29ZOJeaSe8JfyUvphbd221NfXmmsJUGGPGA/nnaSS01tXipUcyxAxg== dependencies: cross-spawn "^7.0.3" node-cleanup "^2.1.2" @@ -7701,7 +9144,7 @@ tsc-watch@^4.2.9: tsconfig@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== dependencies: "@types/strip-bom" "^3.0.0" @@ -7711,12 +9154,12 @@ tsconfig@^7.0.0: tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -7724,13 +9167,13 @@ tsutils@^3.21.0: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + 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" @@ -7738,38 +9181,43 @@ type-check@^0.4.0, type-check@~0.4.0: type-check@~0.3.2: version "0.3.2" resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== dependencies: prelude-ls "~1.1.2" type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: version "4.0.8" - resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== type-fest@^0.21.3: version "0.21.3" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== type-fest@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== type-fest@^0.8.1: version "0.8.1" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.0.1, type-fest@^1.2.1, type-fest@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + type-is@^1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -7777,64 +9225,74 @@ type-is@^1.6.18: typedarray-to-buffer@^3.1.5: version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" + 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@^4.0.3: - version "4.3.5" - resolved "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz" - integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== + version "4.7.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +uid-safe@^2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" + integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== + dependencies: + random-bytes "~1.0.0" uid2@0.0.3: version "0.0.3" resolved "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz" - integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= + integrity sha512-5gSP1liv10Gjp8cMEnFd6shzkL/D6W1uhXSFNCxDC+YI8+L8wkCYCbJ7n77Ezb4wE/xzMogecE+DtamEe9PZjg== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" undefsafe@^2.0.2: - version "2.0.3" - resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz" - integrity sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A== - dependencies: - debug "^2.2.0" + version "2.0.5" + resolved "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz" + integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== +undici@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/undici/-/undici-3.3.6.tgz#06d3b97b7eeff46bce6f8a71079c09f64dd59dc1" + integrity sha512-/j3YTZ5AobMB4ZrTY72mzM54uFUX32v0R/JRW9G2vOyF1uSKYAx+WT8dMsAcRS13TOFISv094TxIyWYk+WEPsA== -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== +unicode-canonical-property-names-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + +unicode-match-property-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" + unicode-canonical-property-names-ecmascript "^2.0.0" + unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== +unicode-match-property-value-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== +unicode-property-aliases-ecmascript@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz" + integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== union-value@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" @@ -7844,24 +9302,24 @@ union-value@^1.0.0: unique-string@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg== dependencies: crypto-random-string "^2.0.0" universalify@^0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== universalify@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== unoconv-promise@^1.0.8: version "1.0.8" - resolved "https://registry.npmjs.org/unoconv-promise/-/unoconv-promise-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/unoconv-promise/-/unoconv-promise-1.0.8.tgz#8d4b9fcba8364908a4910c35899e3ee27a3df24a" integrity sha512-YBVskYpnYj5KQS5aCnE+a+n7jFOmL9dOKzfymw5mKsZhO2K6LrBLAGzReXpOU3x77tTEeJzZYTgrhqIbtF9Acw== dependencies: chai "^4.2.0" @@ -7871,14 +9329,22 @@ unoconv-promise@^1.0.8: unset-value@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + integrity sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ== dependencies: has-value "^0.3.1" isobject "^3.0.0" +update-browserslist-db@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz" + integrity sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + update-notifier@^4.0.0: version "4.1.3" - resolved "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" integrity sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A== dependencies: boxen "^4.2.0" @@ -7897,7 +9363,7 @@ update-notifier@^4.0.0: uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" @@ -7905,36 +9371,36 @@ uri-js@^4.2.2: urix@^0.1.0: version "0.1.0" resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== dependencies: prepend-http "^2.0.0" url-parse@~1.5.1: - version "1.5.3" - resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz" - integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== dependencies: querystringify "^2.1.1" requires-port "^1.0.0" use@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== util@^0.12.3: version "0.12.4" - resolved "https://registry.npmjs.org/util/-/util-0.12.4.tgz" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== dependencies: inherits "^2.0.3" @@ -7947,21 +9413,21 @@ util@^0.12.3: uuid-time@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/uuid-time/-/uuid-time-1.0.0.tgz" - integrity sha1-i7GPpwiZh+8lsMQEcZATPPo6FMY= + integrity sha512-F0EzKK+aqt41uDutE+qukIta0CkMJ212qkIWT7uUCy0DjbyMEGpNkiLQfdByBveEt28Z/ywZU7u4CQ/a03oCaA== uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" - resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== v8-compile-cache@^2.0.3: version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^7.0.0: version "7.1.2" - resolved "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz#30898d1a7fa0c84d225a2c1434fb958f290883c1" integrity sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" @@ -7970,48 +9436,48 @@ v8-to-istanbul@^7.0.0: validate-npm-package-license@^3.0.1: version "3.0.4" - resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz" + 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" -vary@^1.1.2: +vary@^1, vary@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== w3c-hr-time@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== dependencies: browser-process-hrtime "^1.0.0" w3c-xmlserializer@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== dependencies: xml-name-validator "^3.0.0" walker@^1.0.7, walker@~1.0.5: - version "1.0.7" - resolved "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + version "1.0.8" + resolved "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== dependencies: - makeerror "1.0.x" + makeerror "1.0.12" wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" - integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== dependencies: defaults "^1.0.3" web-encoding@^1.1.5: version "1.1.5" - resolved "https://registry.npmjs.org/web-encoding/-/web-encoding-1.1.5.tgz" + resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864" integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA== dependencies: util "^0.12.3" @@ -8021,41 +9487,54 @@ web-encoding@^1.1.5: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== webidl-conversions@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== webidl-conversions@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + whatwg-encoding@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== dependencies: iconv-lite "0.4.24" whatwg-mimetype@^2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" -whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: +whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" - resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77" integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg== dependencies: lodash "^4.7.0" @@ -8064,7 +9543,7 @@ whatwg-url@^8.0.0, whatwg-url@^8.4.0, whatwg-url@^8.5.0: which-boxed-primitive@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== dependencies: is-bigint "^1.0.1" @@ -8076,21 +9555,21 @@ which-boxed-primitive@^1.0.2: which-module@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== which-typed-array@^1.1.2: - version "1.1.6" - resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.6.tgz" - integrity sha512-DdY984dGD5sQ7Tf+x1CkXzdg85b9uEel6nr4UkFg1LoE9OXv3uRuZhe5CoWdawhGACeFpEZXH8fFLQnDhbpm/Q== + version "1.1.8" + resolved "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz" + integrity sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw== dependencies: - available-typed-arrays "^1.0.4" + available-typed-arrays "^1.0.5" call-bind "^1.0.2" - es-abstract "^1.18.5" - foreach "^2.0.5" + es-abstract "^1.20.0" + for-each "^0.3.3" has-tostringtag "^1.0.0" - is-typed-array "^1.1.6" + is-typed-array "^1.1.9" -which@^1.2.9: +which@^1.1.1, which@^1.2.9: version "1.3.1" resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -8099,33 +9578,33 @@ which@^1.2.9: which@^2.0.1, which@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== +wide-align@^1.1.2: + version "1.1.5" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== dependencies: - string-width "^1.0.2 || 2" + string-width "^1.0.2 || 2 || 3 || 4" widest-line@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== dependencies: string-width "^4.0.0" word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + 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.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" + 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" @@ -8134,7 +9613,7 @@ wrap-ansi@^6.2.0: wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -8144,11 +9623,11 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" + 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" @@ -8157,28 +9636,33 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.4.2, ws@^7.4.6: - version "7.5.3" - resolved "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz" - integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== + version "7.5.8" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz" + integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw== ws@~7.4.2: version "7.4.6" - resolved "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== +ws@~8.2.3: + version "8.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" + integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== + xdg-basedir@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== xml-name-validator@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== xml2js@^0.4.15: version "0.4.23" - resolved "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== dependencies: sax ">=0.6.0" @@ -8187,63 +9671,56 @@ xml2js@^0.4.15: xml@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz" - integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== xmlbuilder@~11.0.0: version "11.0.1" - resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== xmlchars@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== xmlhttprequest-ssl@~1.6.2: version "1.6.3" - resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6" integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q== xtend@^4.0.0, xtend@^4.0.2: version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -xtend@~2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - y18n@^4.0.0: version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^4.0.0: +yallist@4.0.0, yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@20.x, yargs-parser@^20.2.2: +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + +yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.9: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-parser@^18.1.2: version "18.1.3" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" @@ -8251,7 +9728,7 @@ yargs-parser@^18.1.2: yargs@^15.4.1: version "15.4.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" + 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" @@ -8268,7 +9745,7 @@ yargs@^15.4.1: yargs@^16.2.0: version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -8282,9 +9759,14 @@ yargs@^16.2.0: yeast@0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz" - integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + integrity sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg== yn@3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/twake/docker-compose.dev.mongo.yml b/twake/docker-compose.dev.mongo.yml index 489b609384..1c948af7fc 100644 --- a/twake/docker-compose.dev.mongo.yml +++ b/twake/docker-compose.dev.mongo.yml @@ -11,7 +11,9 @@ services: node: image: twaketech/twake-node ports: - - 3000:3000 + - 4000:3000 + - 8000:3000 + - 9229:9229 environment: - DEV=dev - SEARCH_DRIVER=mongodb @@ -27,4 +29,4 @@ services: depends_on: - mongo links: - - mongo \ No newline at end of file + - mongo diff --git a/twake/docker-compose.dev.tests.mongo.yml b/twake/docker-compose.dev.tests.mongo.yml index df08689f55..f57066d5e4 100644 --- a/twake/docker-compose.dev.tests.mongo.yml +++ b/twake/docker-compose.dev.tests.mongo.yml @@ -1,13 +1,8 @@ version: "3.4" -# docker-compose -f docker-compose.yml.dist.dev.tests.mongo stop mongo; rm -R docker-data/mongo/; docker-compose -f docker-compose.yml.dist.dev.tests.mongo run -e SEARCH_DRIVER=mongodb -e DB_DRIVER=mongodb node npm run test:e2e +# docker-compose -f docker-compose.dev.tests.mongo.yml stop mongo; rm -R docker-data/mongo/; docker-compose -f docker-compose.dev.tests.mongo.yml run -e SEARCH_DRIVER=mongodb -e DB_DRIVER=mongodb node npm run test:e2e services: - rabbitmq: - image: rabbitmq:3 - ports: - - 5672:5672 - - 15672:15672 mongo: container_name: mongo image: mongo @@ -17,6 +12,7 @@ services: - 27017:27017 node: image: twaketech/twake-node:test + container_name: node-test build: context: . dockerfile: ./docker/twake-node/Dockerfile @@ -30,7 +26,5 @@ services: - ./docker-data/documents/:/storage/ depends_on: - mongo - - rabbitmq links: - mongo - - rabbitmq diff --git a/twake/docker-compose.dev.yml b/twake/docker-compose.dev.yml index 6eb4d81671..d1039ba9b2 100644 --- a/twake/docker-compose.dev.yml +++ b/twake/docker-compose.dev.yml @@ -10,6 +10,7 @@ services: - ./docker-data/scylladb:/var/lib/scylla rabbitmq: image: rabbitmq:3 + node: image: twaketech/twake-node ports: @@ -33,6 +34,8 @@ services: - elasticsearch links: - scylladb + extra_hosts: + - "host.docker.internal:host-gateway" php: image: twaketech/twake-php environment: diff --git a/twake/docker-compose.onpremise.mongo.yml b/twake/docker-compose.onpremise.mongo.yml new file mode 100644 index 0000000000..e313dcee8a --- /dev/null +++ b/twake/docker-compose.onpremise.mongo.yml @@ -0,0 +1,26 @@ +version: "3.4" + +services: + mongo: + container_name: mongo + image: mongo + volumes: + - ./docker-data/mongo:/data/db + + node: + image: twaketech/twake-node:latest + ports: + - 3000:3000 + - 8000:3000 + environment: + - DEV=production + - SEARCH_DRIVER=mongodb + - DB_DRIVER=mongodb + - PUBSUB_TYPE=local + volumes: + - ./configuration/backend-node/production.json:/usr/src/app/config/production.json + - ./docker-data/documents/:/storage/ + depends_on: + - mongo + links: + - mongo diff --git a/twake/docker-compose.onpremise.yml b/twake/docker-compose.onpremise.yml index a85cfb0d4c..2e9d0aa35b 100644 --- a/twake/docker-compose.onpremise.yml +++ b/twake/docker-compose.onpremise.yml @@ -8,43 +8,59 @@ services: - 9042:9042 volumes: - ./docker-data/scylladb:/var/lib/scylla + healthcheck: + test: ["CMD-SHELL", "nodetool status | grep UN"] + interval: 30s + timeout: 10s + retries: 3 rabbitmq: image: rabbitmq:3 + healthcheck: + test: rabbitmq-diagnostics -q ping + interval: 30s + timeout: 10s + retries: 3 node: - image: twaketech/twake-node:2021.Q2.505 + build: + context: . + dockerfile: docker/twake-node/Dockerfile environment: - NODE_ENV=production - PUBSUB_URLS=amqp://guest:guest@rabbitmq:5672 volumes: - - ./configuration/backend-node/production.json:/usr/src/app/config/production.json + - ./default-configuration/backend-node/production.json:/usr/src/app/config/production.json - ./docker-data/documents/:/storage/ depends_on: - - scylladb - - rabbitmq - links: - - scylladb + scylladb: + condition: service_healthy + rabbitmq: + condition: service_healthy php: - image: twaketech/twake-php:2021.Q2.505 + build: + context: . + dockerfile: docker/twake-php/Dockerfile environment: - DEV=production volumes: - - ./configuration/backend/Parameters.php:/configuration/Parameters.php + - ./default-configuration/backend/Parameters.php:/configuration/Parameters.php - ./connectors/:/twake-core/src/BuiltInConnectors/Connectors - ./docker-data/drive/:/twake-core/drive/ - ./docker-data/fpm/:/etc/docker-data/fpm/ - ./docker-data/drive-preview/:/twake-core/web/medias/ - ./docker-data/uploads/:/twake-core/web/upload/ depends_on: - - scylladb - - rabbitmq - links: - - scylladb + scylladb: + condition: service_healthy + rabbitmq: + condition: service_healthy nginx: - image: twaketech/twake-nginx:2021.Q2.505 + build: + context: . + dockerfile: docker/twake-nginx/Dockerfile environment: - DEV=production - SSL_CERTS=selfsigned diff --git a/twake/docker/integration-test/Dockerfile b/twake/docker/integration-test/Dockerfile new file mode 100644 index 0000000000..3be2cdbd36 --- /dev/null +++ b/twake/docker/integration-test/Dockerfile @@ -0,0 +1,20 @@ +FROM node:slim + +# We don't need the standalone Chromium +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true + +# Install Google Chrome Stable and fonts +# Note: this installs the necessary libs to make the browser work with Puppeteer. +RUN apt-get update && apt-get install curl gnupg -y \ + && curl --location --silent https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \ + && sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' \ + && apt-get update \ + && apt-get install google-chrome-stable -y --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY integration-test /app + +RUN npm install + +ENTRYPOINT npm run test:all \ No newline at end of file diff --git a/twake/docker/nginx-static-yarn/Dockerfile b/twake/docker/nginx-static-yarn/Dockerfile deleted file mode 100644 index 6b346d3371..0000000000 --- a/twake/docker/nginx-static-yarn/Dockerfile +++ /dev/null @@ -1,56 +0,0 @@ -# MUST BE BUILT FROM . -# docker build . -t nginx-static-yarn -f ./Dockerfile -FROM debian:11 - -MAINTAINER Romaric Mourgues - -RUN apt-get update && apt-get -y install cron - -RUN apt-get update && apt-get install -y \ - nginx - -RUN apt-get update && apt-get install -y wget - -RUN rm /etc/nginx/sites-enabled/default - -RUN usermod -u 1000 www-data - -RUN apt-get remove certbot -RUN apt-get install -y python3 python3-venv libaugeas0 -RUN python3 -m venv /opt/certbot/ -RUN /opt/certbot/bin/pip install --upgrade pip -RUN /opt/certbot/bin/pip install certbot -RUN ln -s /opt/certbot/bin/certbot /usr/bin/certbot - -RUN apt-get update && apt-get install -y \ - augeas-lenses binutils cpp cpp-8 dh-python gcc gcc-8 libasan5 libatomic1 \ - libaugeas0 libc-dev-bin libc6-dev libcilkrts5 libexpat1-dev \ - libffi-dev libgcc-8-dev libgomp1 libisl19 libitm1 liblsan0 libmpc3 \ - libmpdec2 libmpfr6 libpython-dev libpython-stdlib libpython2.7 \ - libpython2.7-dev libpython2.7-minimal libpython2.7-stdlib libpython3-stdlib \ - libpython3.7-minimal libpython3.7-stdlib libquadmath0 libsqlite3-0 \ - libssl-dev libtsan0 libubsan0 linux-libc-dev mime-support python \ - python-chardet python-colorama python-dev python-distlib \ - python-html5lib python-minimal python-pip-whl python-pkg-resources \ - python-requests python-setuptools python-six python-urllib3 \ - python-virtualenv python2.7 python2.7-dev python2.7-minimal python3 \ - python3-minimal python3-pkg-resources python3-virtualenv python3.7 \ - python3.7-minimal virtualenv zlib1g-dev - - -ADD ./nginx.conf /etc/nginx/nginx.conf - -# Install yarn -RUN apt-get update -RUN apt-get -y install curl -RUN apt-get -y install apt-transport-https ca-certificates apt-utils gnupg -RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - -RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list -RUN apt-get update -RUN apt-get -y install yarn -RUN curl -sL https://deb.nodesource.com/setup_12.x | bash - -RUN apt-get install -y nodejs -RUN yarn global add webpack -RUN yarn global add webpack-cli -RUN apt-get update -RUN apt-get -y install git \ No newline at end of file diff --git a/twake/docker/nginx-static-yarn/nginx.conf b/twake/docker/nginx-static-yarn/nginx.conf deleted file mode 100644 index 68217c5995..0000000000 --- a/twake/docker/nginx-static-yarn/nginx.conf +++ /dev/null @@ -1,65 +0,0 @@ -user www-data; -worker_processes 4; -pid /run/nginx.pid; - -events { - worker_connections 768; - # multi_accept on; -} - -http { - - client_max_body_size 200M; - - ## - # Basic Settings - ## - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - # server_tokens off; - - # server_names_hash_bucket_size 64; - # server_name_in_redirect off; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - ## - # SSL Settings - ## - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE - ssl_prefer_server_ciphers on; - - ## - # Logging Settings - ## - - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - ## - # Gzip Settings - ## - - gzip on; - gzip_disable "msie6"; - - # gzip_vary on; - # gzip_proxied any; - # gzip_comp_level 6; - # gzip_buffers 16 8k; - # gzip_http_version 1.1; - # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - - ## - # Virtual Host Configs - ## - - include /etc/nginx/conf.d/*.conf; - include /etc/nginx/sites-enabled/*; -} diff --git a/twake/docker/twake-nginx-php-only/Dockerfile b/twake/docker/twake-nginx-php-only/Dockerfile index ec856bcca4..97aa8eab0f 100644 --- a/twake/docker/twake-nginx-php-only/Dockerfile +++ b/twake/docker/twake-nginx-php-only/Dockerfile @@ -1,7 +1,42 @@ -# nginx/Dockerfile -FROM twaketech/nginx-static-yarn -MAINTAINER Romaric Mourgues +FROM debian:11 + +RUN apt-get update && apt-get -y install cron + +RUN apt-get update && apt-get install -y \ + nginx + +RUN apt-get update && apt-get install -y wget + +RUN rm /etc/nginx/sites-enabled/default + +RUN usermod -u 1000 www-data + +RUN apt-get remove certbot +RUN apt-get install -y python3 python3-venv libaugeas0 +RUN python3 -m venv /opt/certbot/ +RUN /opt/certbot/bin/pip install --upgrade pip +RUN /opt/certbot/bin/pip install certbot +RUN ln -s /opt/certbot/bin/certbot /usr/bin/certbot + +ADD docker/twake-nginx-php-only/nginx.conf /etc/nginx/nginx.conf + +# Install yarn +RUN apt-get update +RUN apt-get -y install curl +RUN apt-get -y install apt-transport-https ca-certificates apt-utils gnupg +RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - +RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list +RUN apt-get update +RUN apt-get -y install yarn +RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - +RUN apt-get install -y nodejs +RUN yarn global add webpack +RUN yarn global add webpack-cli +RUN apt-get update +RUN apt-get -y install git + +# Install php ADD docker/twake-nginx/site.conf /etc/nginx/sites-available/site.template ADD docker/twake-nginx-php-only/nginx.conf /etc/nginx/nginx.conf diff --git a/twake/docker/twake-nginx/Dockerfile b/twake/docker/twake-nginx/Dockerfile old mode 100644 new mode 100755 index 089473f786..144df56c9e --- a/twake/docker/twake-nginx/Dockerfile +++ b/twake/docker/twake-nginx/Dockerfile @@ -1,31 +1,31 @@ -FROM twaketech/nginx-static-yarn +# First stage: building frontend +FROM node:lts AS build -MAINTAINER Romaric Mourgues - -ADD docker/twake-nginx/site.conf /etc/nginx/sites-available/site.template -ADD docker/twake-nginx/redirect.conf /etc/nginx/sites-available/redirect -ADD docker/twake-nginx-php-only/nginx.conf /etc/nginx/nginx.conf -RUN apt-get update && apt-get install gettext-base -RUN echo "upstream php-upstream { server php:9000; }" > /etc/nginx/conf.d/upstream.conf +RUN yarn global add webpack webpack-cli +COPY frontend /twake-react/ WORKDIR /twake-react/ -COPY frontend /twake-react/ -RUN cp /twake-react/src/app/environment/environment.ts.dist /twake-react/src/app/environment/environment.ts -RUN yarn install --network-timeout 1000000000 -ENV GENERATE_SOURCEMAP false -RUN cat /twake-react/src/app/environment/environment.ts.dist -RUN cat /twake-react/src/app/environment/environment.ts ENV GENERATE_SOURCEMAP=false -RUN yarn build -RUN rm -R node_modules - -RUN cp /twake-react/src/app/environment/environment.ts.dist /environment.ts.dist +RUN cp /twake-react/src/app/environment/environment.ts.dist /twake-react/src/app/environment/environment.ts && \ + yarn install --network-timeout 1000000000 && \ + # cat /twake-react/src/app/environment/environment.ts.dist && \ + # cat /twake-react/src/app/environment/environment.ts && \ + yarn build && \ + rm -rf node_modules +# Second stage: configuring nginx and copying build artifacts +FROM nginx:latest +COPY docker/twake-nginx/nginx.conf /etc/nginx/nginx.conf +COPY docker/twake-nginx/site.conf /etc/nginx/sites-available/site.template +COPY docker/twake-nginx/redirect.conf /etc/nginx/sites-available/redirect COPY docker/twake-nginx/entrypoint.sh / COPY docker/twake-nginx/self-signed.sh /usr/local/bin/ -RUN chmod 0777 /entrypoint.sh -ENTRYPOINT /entrypoint.sh "$DEV" +COPY --from=build /twake-react /twake-react + +RUN chmod +x /entrypoint.sh && rm /etc/nginx/conf.d/default.conf + +ENTRYPOINT ["/entrypoint.sh", "$DEV"] EXPOSE 80 EXPOSE 443 diff --git a/twake/docker/twake-nginx/entrypoint.sh b/twake/docker/twake-nginx/entrypoint.sh old mode 100644 new mode 100755 index b2bf695673..2d7ee37c4d --- a/twake/docker/twake-nginx/entrypoint.sh +++ b/twake/docker/twake-nginx/entrypoint.sh @@ -15,6 +15,8 @@ else fi fi +[[ -d "/etc/nginx/sites-enabled" ]] || mkdir /etc/nginx/sites-enabled + function _selfsigned() { self-signed.sh export NGINX_LISTEN="443 ssl" @@ -43,5 +45,4 @@ export PHP_UPSTREAM envsubst '$${NODE_HOST} $${NGINX_LISTEN}' < /etc/nginx/sites-available/site.template > /etc/nginx/sites-enabled/site echo "upstream php-upstream { server ${PHP_UPSTREAM}; }" > /etc/nginx/conf.d/upstream.conf -cron -f & nginx -g "daemon off;" diff --git a/twake/docker/twake-nginx/site.conf b/twake/docker/twake-nginx/site.conf index 35b0458970..38ac6c63be 100644 --- a/twake/docker/twake-nginx/site.conf +++ b/twake/docker/twake-nginx/site.conf @@ -9,6 +9,30 @@ server { add_header Strict-Transport-Security "max-age=31536000"; + location /.well-known { + alias /twake-react/build/.well-known/; + + gzip on; + gzip_disable "msie6"; + + add_header Cache-Control "no-store, public, max-age=0"; + add_header Cross-Origin-Opener-Policy 'same-origin-allow-popups; report-to="DurableDeepLinkUi"'; + add_header Cross-Origin-Resource-Policy "same-site"; + add_header Content-Type "application/json; charset=utf-8"; + add_header Last-Modified ""; + add_header Vary "Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site"; + add_header X-Content-Type-Options "nosniff"; + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-XSS-Protection "0"; + + proxy_buffering off; + if_modified_since off; + expires 0s; + allow all; + + try_files $uri /index.html; + } + location / { gzip on; gzip_disable "msie6"; @@ -34,12 +58,17 @@ server { try_files $uri /index.html; } + location ~ ^/(api/v1).* { + # try to serve file directly, fallback to rewrite + try_files $uri @rewriteapp; + } + location ~ ^/(internal|plugins).* { proxy_set_header X-Forwarded-Host $host; proxy_pass ${NODE_HOST}; } - location ~ ^/(api|administration)/v2/.* { + location ~ ^/(api|administration/v2/).* { proxy_set_header X-Forwarded-Host $host; proxy_pass ${NODE_HOST}; } diff --git a/twake/docker/twake-node/Dockerfile b/twake/docker/twake-node/Dockerfile old mode 100644 new mode 100755 index 5d1d2f10b7..344cc8fdaf --- a/twake/docker/twake-node/Dockerfile +++ b/twake/docker/twake-node/Dockerfile @@ -1,19 +1,16 @@ # Common node machine -FROM node:16-bullseye-slim as node-base +FROM node:lts as node-base ### Install dependancies - -#Imagick -RUN apt-get update && apt-get install -y ghostscript && apt-get clean -RUN apt-get update && apt-get install -y graphicsmagick - -#Unoconv -RUN apt-get update && apt-get install -y --force-yes unoconv libxml2-dev -RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - +RUN apt-get update && \ + apt-get install -y ghostscript graphicsmagick wget unoconv libxml2-dev ffmpeg python-is-python3 && \ + # upgrade unoconv + wget -N https://raw.githubusercontent.com/dagwieers/unoconv/master/unoconv -O /usr/bin/unoconv && \ + chmod +x /usr/bin/unoconv #Docker mac issue -RUN apt-get update && apt-get install -y libc6 -RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 +# RUN apt-get update && apt-get install -y libc6 +# RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 + ### Install Twake @@ -26,43 +23,44 @@ FROM node-base as test RUN npm install COPY backend/node/ . -# Development Stage -FROM node-base as development +# Add frontend Stage +FROM node-base as with-frontend -RUN npm install -g pino-pretty -RUN npm install -g tsc-watch -RUN npm install COPY backend/node/ . +#Install dev dependancies for build +RUN NODE_ENV=development npm install && \ + #Build in production mode + export NODE_ENV=production && \ + npm run build && \ + rm -rf node_modules && \ + #Install prod dependancies after build + npm install --legacy-peer-deps -CMD ["npm", "run", "dev"] - -# Production Stage -FROM node-base as production +# Add frontend into node +COPY frontend/ ../public_build/ +RUN export NODE_ENV=development && \ + apt-get install -y build-essential && \ + cd ../public_build/ && \ + yarn install --network-timeout 1000000000 && \ + yarn global add webpack webpack-cli jest && \ + cp src/app/environment/environment.ts.dist src/app/environment/environment.ts && \ + export NODE_ENV=production && \ + yarn build && \ + rm -R node_modules && \ + mv build/* ../app/public && \ + cd .. && rm -R public_build/ -ARG NODE_ENV=production +# Development Stage +FROM with-frontend as development ENV NODE_ENV=development -RUN npm install #Install dev dependancies for build -COPY backend/node/ . -ENV NODE_ENV=${NODE_ENV} -RUN npm run build #Build in production mode -RUN rm -R node_modules -RUN npm install #Install prod dependancies after build +RUN npm install -g pino-pretty && \ + npm install -g tsc-watch && \ + yarn install +CMD ["npm", "run", "dev:debug"] -# Add frontend into node -ENV NODE_ENV=development -COPY frontend/ ../public_build/ -RUN apt-get install -y build-essential -RUN cd ../public_build && yarn install --network-timeout 1000000000 -RUN yarn global add webpack && yarn global add webpack-cli && yarn global add jest -RUN cp ../public_build/src/app/environment/environment.ts.dist ../public_build/src/app/environment/environment.ts -ENV NODE_ENV=${NODE_ENV} -RUN cd ../public_build && yarn build -RUN cd ../public_build && rm -R node_modules -RUN mv ../public_build/build public; rm -R ../public_build +# Production Stage +FROM with-frontend as production EXPOSE 3000 - CMD ["npm", "run", "serve"] - - diff --git a/twake/docker/twake-php/Dockerfile b/twake/docker/twake-php/Dockerfile old mode 100644 new mode 100755 index 27f3474259..dd57e7bd28 --- a/twake/docker/twake-php/Dockerfile +++ b/twake/docker/twake-php/Dockerfile @@ -1,20 +1,18 @@ FROM twaketech/php7.1-cassandra -MAINTAINER Romaric Mourgues +LABEL org.opencontainers.image.authors="Romaric Mourgues ,Nguyen Thai " #Crontab ADD docker/twake-php/crontab /etc/cron.d/twake-cron -RUN chmod 0644 /etc/cron.d/twake-cron -RUN touch /var/log/cron.log - -RUN mkdir /twake-core/ COPY backend/core/ /twake-core/ -RUN cd /twake-core/ && php composer.phar install - COPY docker/twake-php/entrypoint.sh / -RUN chmod 0777 /entrypoint.sh + +RUN chmod 0644 /etc/cron.d/twake-cron && \ + touch /var/log/cron.log && \ + cd /twake-core/ && php composer.phar install && \ + chmod +x /entrypoint.sh #For exec WORKDIR /twake-core/ -ENTRYPOINT /entrypoint.sh "$DEV" +ENTRYPOINT ["/entrypoint.sh", "$DEV"] diff --git a/twake/docker/twake-plugins/Dockerfile b/twake/docker/twake-plugins/Dockerfile new file mode 100644 index 0000000000..4d44df0d92 --- /dev/null +++ b/twake/docker/twake-plugins/Dockerfile @@ -0,0 +1,48 @@ +# Common node machine +FROM node:16-bullseye-slim as node-base + +### Install dependancies + +#Docker mac issue +RUN apt-get update && apt-get install -y libc6 +RUN ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 + +### Install Twake + +WORKDIR /usr/src/app +COPY backend/node/package*.json ./ + +# Test Stage +FROM node-base as test + +RUN npm install +COPY backend/node/ . + +# Development Stage +FROM node-base as development + +RUN npm install -g pino-pretty +RUN npm install -g tsc-watch +RUN npm install +COPY backend/node/ . + +CMD ["npm", "run", "dev"] + +# Production Stage +FROM node-base as production + +ARG NODE_ENV=production + +ENV NODE_ENV=development +RUN npm install #Install dev dependancies for build +COPY backend/node/ . +ENV NODE_ENV=${NODE_ENV} +RUN npm run build #Build in production mode +RUN rm -R node_modules +RUN npm install #Install prod dependancies after build + +EXPOSE 3000 + +CMD ["npm", "run", "serve"] + + diff --git a/twake/frontend/.eslintrc.js b/twake/frontend/.eslintrc.js new file mode 100644 index 0000000000..770018287c --- /dev/null +++ b/twake/frontend/.eslintrc.js @@ -0,0 +1,39 @@ +module.exports = { + env: { + browser: true, + es2021: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: ['react', 'react-hooks', 'eslint-plugin-jsx-a11y', '@typescript-eslint'], + ignorePatterns: ['**/deprecated/*.js'], + rules: { + 'react/display-name': 'off', + '@typescript-eslint/triple-slash-reference': 'off', + 'react/react-in-jsx-scope': 'off', + 'jsx-a11y/anchor-is-valid': 'off', + 'react-hooks/exhaustive-deps': 'off', + 'react/no-children-prop': 'off', + 'react/no-unescaped-entities': 'off', + 'no-async-promise-executor': 'off', + 'no-control-regex': 'warn', + '@typescript-eslint/no-this-alias': 'warn', + 'react/prop-types': 'warn', + 'no-useless-escape': 'warn', + '@typescript-eslint/no-empty-function': 'warn', + '@typescript-eslint/ban-types': 'warn', + '@typescript-eslint/ban-ts-comment': 'warn', + 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }], + }, +}; diff --git a/twake/frontend/.eslintrc.json b/twake/frontend/.eslintrc.json deleted file mode 100644 index e699c36853..0000000000 --- a/twake/frontend/.eslintrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "extends": [ - "react-app" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true - } - }, - "plugins": [ - "react", - "react-hooks" - ], - "rules": { - "semi": "warn", - "react-hooks/rules-of-hooks": "warn", // Checks rules of Hooks - "react-hooks/exhaustive-deps": "warn", // Checks effect dependencies - "no-use-before-define": "off", - "@typescript-eslint/no-use-before-define": "off", - "@typescript-eslint/no-unused-vars": "off", - "no-control-regex": 0 - } -} \ No newline at end of file diff --git a/twake/frontend/.gitignore b/twake/frontend/.gitignore index 03eaca66b4..9b9a9e1a8a 100644 --- a/twake/frontend/.gitignore +++ b/twake/frontend/.gitignore @@ -15,17 +15,20 @@ .env.development.local .env.test.local .env.production.local +.bin npm-debug.log* yarn-debug.log* yarn-error.log* /.bin/ -/.storybook/ /.idea/ /public/dist/ /public/public/dist/ /storybook-static/ +/public/storybook/ +/public/styles/tailwind.css /build/ /counter-clone/ -__old \ No newline at end of file +__old +/public/styles/tailwind.css \ No newline at end of file diff --git a/twake/frontend/.storybook/__mocks__/languages-service.js b/twake/frontend/.storybook/__mocks__/languages-service.js new file mode 100644 index 0000000000..4d4230c82e --- /dev/null +++ b/twake/frontend/.storybook/__mocks__/languages-service.js @@ -0,0 +1,9 @@ +import en from '../../public/locales/en.json'; + +export default { + t: term => en[term] || term, +} + +export function decorator(story) { + return story(); +} diff --git a/twake/frontend/.storybook/addons.js b/twake/frontend/.storybook/addons.js deleted file mode 100755 index b3227711c9..0000000000 --- a/twake/frontend/.storybook/addons.js +++ /dev/null @@ -1,8 +0,0 @@ -import '@storybook/addon-actions/register'; -import '@storybook/addon-links/register'; -import '@storybook/addon-knobs/register'; -import '@storybook/addon-storysource/register'; -import '@storybook/addon-options/register'; -import '@storybook/addon-notes/register'; -import '@dump247/storybook-state/register'; -import 'storybook-addon-specifications/register'; diff --git a/twake/frontend/.storybook/config.js b/twake/frontend/.storybook/config.js deleted file mode 100755 index cdbf766e4a..0000000000 --- a/twake/frontend/.storybook/config.js +++ /dev/null @@ -1,19 +0,0 @@ -import { configure, addParameters } from '@storybook/react'; -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -addParameters({ - options: { - name: "Twake Storybook", - sortStoriesByKind: true - } -}) - -// automatically import all files ending in *.stories.js -const req = require.context('../stories', true, /\.stories\.js$/); -function loadStories() { - req.keys().forEach(filename => req(filename)); -} - -Enzyme.configure({ adapter: new Adapter() }); -configure(loadStories, module); diff --git a/twake/frontend/.storybook/main.js b/twake/frontend/.storybook/main.js new file mode 100644 index 0000000000..5838a02942 --- /dev/null +++ b/twake/frontend/.storybook/main.js @@ -0,0 +1,77 @@ +const path = require('path'); +const alias = require('../tsconfig.paths.json'); +const webpack = require("webpack"); + +module.exports = { + stories: ['../src/app/**/*.stories.tsx'], + addons: [ + '@storybook/addon-links', + '@storybook/addon-essentials', + '@storybook/preset-create-react-app', + 'storybook-dark-mode', + ], + framework: '@storybook/react', + webpackFinal(config, { configType }) { + let updatedAlias = {}; + for (const key in alias?.compilerOptions?.paths || {}) { + updatedAlias[key.replace(/\/\*$/, '')] = path.resolve( + __dirname, + '../' + alias?.compilerOptions?.paths?.[key][0].replace(/\/\*$/, ''), + ); + } + config = { + ...config, + resolve: { + ...config.resolve, + roots: [ + ...(config.resolve.roots || []), + path.resolve(__dirname, '../public'), + 'node_modules', + ], + alias: { + ...updatedAlias, + ...config.resolve.alias, + }, + }, + }; + + config.module.rules.push({ + test: /\,css&/, + use: [ + { + loader: 'postcss-loader', + options: { + ident: 'postcss', + plugins: [require('tailwindcss'), require('autoprefixer')], + }, + }, + ], + include: path.resolve(__dirname, '../'), + }); + + config.plugins.push( + new webpack.NormalModuleReplacementPlugin( + /languages-service/, + path.resolve(__dirname, './__mocks__/languages-service.js'), + ) + ); + + return config; + }, + babel: async options => ({ + ...options, + presets: [ + ...options.presets, + [ + '@babel/preset-react', + { + runtime: 'automatic', + }, + 'preset-react-jsx-transform', // Can name this anything, just an arbitrary alias to avoid duplicate presets' + ], + ], + }), + core: { + builder: 'webpack5', + } +}; diff --git a/twake/frontend/.storybook/preview.js b/twake/frontend/.storybook/preview.js new file mode 100644 index 0000000000..7a05683443 --- /dev/null +++ b/twake/frontend/.storybook/preview.js @@ -0,0 +1,20 @@ +import '../src/tailwind.css'; + +export const parameters = { + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + previewTabs: { + 'storybook/docs/panel': { index: -1 }, + }, + darkMode: { + stylePreview: true, + }, + docs: { + source: { type: 'code' } + }, +}; diff --git a/twake/frontend/.storybook/webpack.config.js b/twake/frontend/.storybook/webpack.config.js deleted file mode 100755 index ca0bcdf714..0000000000 --- a/twake/frontend/.storybook/webpack.config.js +++ /dev/null @@ -1,28 +0,0 @@ -const path = require('path'); -const custom = require('../webpack.common.js'); - - -module.exports = async ({ config, mode }) => { - config.module.rules = (config.module.rules || []).concat(custom.module.rules); - config.resolve.alias = custom.resolve.alias; - - config.module.rules.push({ - test: /\.stories\.jsx?$/, - loaders: [require.resolve('@storybook/addon-storysource/loader')], - enforce: 'pre', - }); - - var externals = { - 'jsdom': 'window', - 'cheerio': 'window', - 'react/lib/ExecutionEnvironment': true, - 'react/lib/ReactContext': 'window', - 'react/addons': true, - }; - config.externals = config.externals || {}; - Object.keys(externals).forEach((key)=>{ - config.externals[key] = externals[key]; - }) - - return config; -}; diff --git a/twake/frontend/craco.config.js b/twake/frontend/craco.config.js index 85f7f1d2ad..c202f5dda4 100644 --- a/twake/frontend/craco.config.js +++ b/twake/frontend/craco.config.js @@ -1,5 +1,5 @@ -const CracoLessPlugin = require("craco-less"); -const CracoAlias = require("craco-alias"); +const CracoLessPlugin = require('craco-less'); +const CracoAlias = require('craco-alias'); module.exports = { plugins: [ @@ -16,13 +16,13 @@ module.exports = { { plugin: CracoAlias, options: { - source: "tsconfig", + source: 'tsconfig', // baseUrl SHOULD be specified // plugin does not take it from tsconfig - baseUrl: ".", + baseUrl: '.', // tsConfigPath should point to the file where "baseUrl" and "paths" are specified - tsConfigPath: "./tsconfig.paths.json" - } - } + tsConfigPath: './tsconfig.paths.json', + }, + }, ], }; diff --git a/twake/frontend/package-lock.json b/twake/frontend/package-lock.json new file mode 100644 index 0000000000..ce31ddc7b1 --- /dev/null +++ b/twake/frontend/package-lock.json @@ -0,0 +1,44212 @@ +{ + "name": "twake", + "version": "2020.3.107", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "requires": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "@ant-design/icons": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-4.7.0.tgz", + "integrity": "sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g==", + "requires": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-util": "^5.9.4" + } + }, + "@ant-design/icons-svg": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.2.1.tgz", + "integrity": "sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==" + }, + "@ant-design/react-slick": { + "version": "0.29.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-0.29.2.tgz", + "integrity": "sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==", + "requires": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "lodash": "^4.17.21", + "resize-observer-polyfill": "^1.5.1" + } + }, + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz", + "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==" + }, + "@babel/core": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz", + "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==", + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/eslint-parser": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.18.9.tgz", + "integrity": "sha512-KzSGpMBggz4fKbRbWLNyPVTuQr6cmCcBhOyXTw/fieOVaw5oYAwcAj4a7UKcDYCPxQq+CG1NCDZH9e2JTXquiQ==", + "requires": { + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + } + } + }, + "@babel/generator": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz", + "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==", + "requires": { + "@babel/types": "^7.18.13", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz", + "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz", + "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==", + "requires": { + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-plugin-utils": "^7.16.7", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.53.tgz", + "integrity": "sha512-jLbME3MfCVT88GLuUDJ1X+ErDeWi59aeBb/O6pyhp5C+eVRRiLxzptRmpvJqG+Va6aOBWSoJ8uBNKJ1ghT/ONg==", + "requires": { + "@babel/types": "7.0.0-beta.53" + }, + "dependencies": { + "@babel/types": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.53.tgz", + "integrity": "sha512-iL3DSWjQ890rA97uR5F1PhGtYniVGjqaRoRZtLz76bZhNNqmALftafrUnuJNzWC9z0eoaNcAtk7ZT/26mW/6Tg==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.5", + "to-fast-properties": "^2.0.0" + } + } + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" + }, + "@babel/helper-wrap-function": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", + "requires": { + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" + } + }, + "@babel/helpers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "requires": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz", + "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", + "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.18.10.tgz", + "integrity": "sha512-5H2N3R2aQFxkV4PIBUR/i7PUSwgTZjouJKzI8eKswfIjT0PhvzkPn0t0wIS5zn6maQuvtT0t1oHtMUz61LOuow==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-default-from": "^7.18.6" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.18.6.tgz", + "integrity": "sha512-fqyLgjcxf/1yhyZ6A+yo1u9gJ7eleFQod2lkaUsF9DQ7sbbY3Ligym3L0+I2c0WmqNKDpoD9UTb1AKP3qRMOAQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.18.6.tgz", + "integrity": "sha512-Kr//z3ujSVNx6E9z9ih5xXXMqK07VVTuqPmqGe6Mss/zW5XPeLZeSDZoP9ab/hT4wPKqAgjl2PnhPrcpk8Seew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", + "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz", + "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz", + "integrity": "sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "requires": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-constant-elements": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.18.12.tgz", + "integrity": "sha512-Q99U9/ttiu+LMnRU8psd23HhvwXmKWDQIpocm0JKaICcZHnw+mdQbHm6xnSy7dOl8I5PELakYtNBubNQlBXbZw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz", + "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz", + "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-jsx": "^7.18.6", + "@babel/types": "^7.18.10" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz", + "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==", + "requires": { + "@babel/plugin-transform-react-jsx": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.18.6.tgz", + "integrity": "sha512-A0LQGx4+4Jv7u/tWzoJF7alZwnBDQd6cGLh9P+Ttk4dpiL+J5p7NSNv/9tlEFFJDq3kjxOavWmbm6t0Gk+A3Ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.18.6.tgz", + "integrity": "sha512-utZmlASneDfdaMh0m/WausbjUjEdGrQJz0vFK93d7wD3xf5wBtX219+q6IlCNZeguIcxS2f/CvLZrlLSvSHQXw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz", + "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz", + "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==", + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz", + "integrity": "sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-env": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + } + }, + "@babel/preset-es2017": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/preset-es2017/-/preset-es2017-7.0.0-beta.53.tgz", + "integrity": "sha512-kFRWUrg0Fd9+R7uBP5T/MwzdheKCvBtTgyFh/gMlNKQqoV3l2qMJpetDzR4iBrtBCC/xwWS7HO2tK3RV7uJRPw==", + "requires": { + "@babel/helper-plugin-utils": "7.0.0-beta.53", + "@babel/plugin-transform-async-to-generator": "7.0.0-beta.53" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.53.tgz", + "integrity": "sha512-6o6EnDfG+zQqfrYDLPc5kGp6+klZFFFqGucljRcUa7IZuTBpvALWG0O+7rtOGFF1sYhr4jBib995RvFuNFxDMw==", + "requires": { + "@babel/highlight": "7.0.0-beta.53" + } + }, + "@babel/generator": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.0.0-beta.53.tgz", + "integrity": "sha512-XnfdZ6oFVC4cE4+7jbEa1MLFSXrGY/SfSE6onUyyPSrRbjYs9sdrYKi/JgKGSJX65A8GFswHwWcBPCynfVEr5g==", + "requires": { + "@babel/types": "7.0.0-beta.53", + "jsesc": "^2.5.1", + "lodash": "^4.17.5", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0-beta.53.tgz", + "integrity": "sha512-HVsEm3wjSe3BCXWxnyqrTWWQAxvtHR35F4q84jS68aS8R3WfbOnFEwlqsrWX5quZL0ArR68REOWRDCyG+JBSlQ==", + "requires": { + "@babel/types": "7.0.0-beta.53" + } + }, + "@babel/helper-function-name": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.53.tgz", + "integrity": "sha512-vmdaNg17OWa0lFVJqZLQcvc59KIOcJDpyvqr3EJT9BYsjh/JxDlYq/JpBzLpWv9AkXeBdY4NevZXD37gdsLu0Q==", + "requires": { + "@babel/helper-get-function-arity": "7.0.0-beta.53", + "@babel/template": "7.0.0-beta.53", + "@babel/types": "7.0.0-beta.53" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0-beta.53.tgz", + "integrity": "sha512-nyyERQH7kRCy0OR2Ek0+sD+wxZEhCmaLAVE7SylPYmCce1Dq8XGmibT1eQVekRkr78utXnDKMe4A269SBVlIRA==", + "requires": { + "@babel/types": "7.0.0-beta.53", + "lodash": "^4.17.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0-beta.53.tgz", + "integrity": "sha512-ziTIzKm3Hj8LvmV6HwyPC2t2NgSNg2T72Cifqaw3zo44ATRUeNI/nH7NoQZChNNwye97pbzs+UAHq6fCTt3uFg==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.0.0-beta.53.tgz", + "integrity": "sha512-yVndfFtBJjwX1QuE1ks8FEHyJkxAXKZfykk/PPprhd4zWJZRBh0UgtV6uHcb302s2wPQ/6cUgB4GEF8z9aN2DQ==", + "requires": { + "@babel/helper-annotate-as-pure": "7.0.0-beta.53", + "@babel/helper-wrap-function": "7.0.0-beta.53", + "@babel/template": "7.0.0-beta.53", + "@babel/traverse": "7.0.0-beta.53", + "@babel/types": "7.0.0-beta.53" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.53.tgz", + "integrity": "sha512-7twjNOXZFIuiGpfkaf2j1WuGFbfrmHS5ES9GXXXT0xbQ5UmyX9nvaTJHMt11t6pvIjv1xvtBVuDyMCrvyd+E/w==", + "requires": { + "@babel/types": "7.0.0-beta.53" + } + }, + "@babel/helper-wrap-function": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.0.0-beta.53.tgz", + "integrity": "sha512-BAjHzqq+lkhepz79vY0eZ7WfBl09XGDsHrqfCN2fg2PLipWZYJR0O8rP94YUTpS0gy1AIB4lCQl/5dV4SvMV9A==", + "requires": { + "@babel/helper-function-name": "7.0.0-beta.53", + "@babel/template": "7.0.0-beta.53", + "@babel/traverse": "7.0.0-beta.53", + "@babel/types": "7.0.0-beta.53" + } + }, + "@babel/highlight": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0-beta.53.tgz", + "integrity": "sha512-5wvZd8RHAOzmTJ5bpupKM6x5OWXlViUK5ACDAUn7YXDd/JqQQZXi0CxDb8pH5IFV79mt6r5A/bZ/+NLhxpcZ5g==", + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^3.0.0" + } + }, + "@babel/parser": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.0.0-beta.53.tgz", + "integrity": "sha512-SYoyLjcE+D28Ly2kkPXP6eIVy4YwViRSffri5WHi8PRxy8ngnx6mTXFzGAsSSPzUN3DK+sf8qBsdDGeQz1SJEw==" + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.0.0-beta.53.tgz", + "integrity": "sha512-CQQJkRgY/Zt6ezbk4yk1offtvjGzX8MsZC8q39PMj3zKfmawzfRqcBO5O00vw3MgoeAju4/ZZ1gtCzhhNqtgYg==", + "requires": { + "@babel/helper-module-imports": "7.0.0-beta.53", + "@babel/helper-plugin-utils": "7.0.0-beta.53", + "@babel/helper-remap-async-to-generator": "7.0.0-beta.53" + } + }, + "@babel/template": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.0.0-beta.53.tgz", + "integrity": "sha512-MCZLPfGfNBHdE5wNfY5eK1hpY3fyq8zq+NfbfFCUtIzHl7SfUzHzH8rKPBXSB2Ypetq2sBHdDyslSSgnG0Watg==", + "requires": { + "@babel/code-frame": "7.0.0-beta.53", + "@babel/parser": "7.0.0-beta.53", + "@babel/types": "7.0.0-beta.53", + "lodash": "^4.17.5" + } + }, + "@babel/traverse": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.0.0-beta.53.tgz", + "integrity": "sha512-JZh3vX/9ox9aoub2gLlpPRm8LM0yJuqzmp5MrbwD57SPh1dHMDWjGen9exbaITAe03t9MJV5PAacv0K2UJBffg==", + "requires": { + "@babel/code-frame": "7.0.0-beta.53", + "@babel/generator": "7.0.0-beta.53", + "@babel/helper-function-name": "7.0.0-beta.53", + "@babel/helper-split-export-declaration": "7.0.0-beta.53", + "@babel/parser": "7.0.0-beta.53", + "@babel/types": "7.0.0-beta.53", + "debug": "^3.1.0", + "globals": "^11.1.0", + "invariant": "^2.2.0", + "lodash": "^4.17.5" + } + }, + "@babel/types": { + "version": "7.0.0-beta.53", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.0.0-beta.53.tgz", + "integrity": "sha512-iL3DSWjQ890rA97uR5F1PhGtYniVGjqaRoRZtLz76bZhNNqmALftafrUnuJNzWC9z0eoaNcAtk7ZT/26mW/6Tg==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.5", + "to-fast-properties": "^2.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==" + } + } + }, + "@babel/preset-flow": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.18.6.tgz", + "integrity": "sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-flow-strip-types": "^7.18.6" + }, + "dependencies": { + "@babel/plugin-transform-flow-strip-types": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.18.9.tgz", + "integrity": "sha512-+G6rp2zRuOAInY5wcggsx4+QVao1qPM0osC9fTUVlAV3zOrzTCnrMAFVnR6+a3T8wz1wFIH7KhYMcMB3u1n80A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-flow": "^7.18.6" + } + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz", + "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-react-display-name": "^7.18.6", + "@babel/plugin-transform-react-jsx": "^7.18.6", + "@babel/plugin-transform-react-jsx-development": "^7.18.6", + "@babel/plugin-transform-react-pure-annotations": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz", + "integrity": "sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.9.0" + } + }, + "@babel/register": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", + "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "@babel/runtime": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs2": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.18.9.tgz", + "integrity": "sha512-l057ZarpDX2QnXM89ViR2BgRFgTy2l5UFGDt0SbInhim1N/ljBgPeTJV0kRG1/Bo7CkHfYfrNNwTeQ2CPph9xQ==", + "requires": { + "core-js": "^2.6.12", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz", + "integrity": "sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==", + "requires": { + "core-js-pure": "^3.20.2", + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz", + "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.18.13", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz", + "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==", + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "optional": true + }, + "@craco/craco": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@craco/craco/-/craco-6.4.5.tgz", + "integrity": "sha512-8F2rIAao8sEh0FPP52ViEvDM9GjJ7acq0knu1c8UgI+EuZMD5/ZB270ol6jV4iNY7it9Umg/RoGBvNRUNr8U8w==", + "requires": { + "cosmiconfig": "^7.0.1", + "cosmiconfig-typescript-loader": "^1.0.0", + "cross-spawn": "^7.0.0", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "webpack-merge": "^4.2.2" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==" + }, + "@csstools/normalize.css": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", + "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==" + }, + "@csstools/postcss-cascade-layers": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.0.5.tgz", + "integrity": "sha512-Id/9wBT7FkgFzdEpiEWrsVd4ltDxN0rI0QS0SChbeQiSuux3z21SJCRLu6h2cvCEUmaRi+VD0mHFj+GJD4GFnw==", + "requires": { + "@csstools/selector-specificity": "^2.0.2", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-color-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", + "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-font-format-keywords": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", + "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-hwb-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", + "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-ic-unit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", + "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-is-pseudo-class": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", + "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "@csstools/postcss-nested-calc": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", + "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-normalize-display-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", + "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-oklab-function": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", + "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-progressive-custom-properties": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", + "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-stepped-value-functions": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", + "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-text-decoration-shorthand": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", + "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-trigonometric-functions": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", + "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "@csstools/postcss-unset-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", + "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==" + }, + "@csstools/selector-specificity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", + "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==" + }, + "@ctrl/tinycolor": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.4.1.tgz", + "integrity": "sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==" + }, + "@design-systems/utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@design-systems/utils/-/utils-2.12.0.tgz", + "integrity": "sha512-Y/d2Zzr+JJfN6u1gbuBUb1ufBuLMJJRZQk+dRmw8GaTpqKx5uf7cGUYGTwN02dIb3I+Tf+cW8jcGBTRiFxdYFg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.11.2", + "clsx": "^1.0.4", + "focus-lock": "^0.8.0", + "react-merge-refs": "^1.0.0" + } + }, + "@devtools-ds/object-inspector": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@devtools-ds/object-inspector/-/object-inspector-1.2.0.tgz", + "integrity": "sha512-VztcwqVwScSvYdvJVZBJYsVO/2Pew3JPpFV3T9fuCHQLlHcLYOV3aU/kBS2ScuE2O1JN0ZbobLqFLa3vQF54Fw==", + "dev": true, + "requires": { + "@babel/runtime": "7.7.2", + "@devtools-ds/object-parser": "^1.2.0", + "@devtools-ds/themes": "^1.2.0", + "@devtools-ds/tree": "^1.2.0", + "clsx": "1.1.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", + "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "clsx": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", + "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", + "dev": true + } + } + }, + "@devtools-ds/object-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@devtools-ds/object-parser/-/object-parser-1.2.0.tgz", + "integrity": "sha512-SjGGyiFFY8dtUpiWXAvRSzRT+hE11EAAysrq2PsC/GVLf2ZLyT2nHlQO5kDStywyTz+fjw7S7pyDRj1HG9YTTA==", + "dev": true, + "requires": { + "@babel/runtime": "~7.5.4" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", + "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + } + } + }, + "@devtools-ds/themes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@devtools-ds/themes/-/themes-1.2.0.tgz", + "integrity": "sha512-LimEITorE6yWZWWuMc6OiBfLQgPrQqWbyMEmfRUDPa3PHXoAY4SpDxczfg31fgyRDUNWnZhjaJH5bBbu8VEbIw==", + "dev": true, + "requires": { + "@babel/runtime": "~7.5.4", + "@design-systems/utils": "2.12.0", + "clsx": "1.1.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.5.5.tgz", + "integrity": "sha512-28QvEGyQyNkB0/m2B4FU7IEZGK2NUrcMtT6BZEFALTguLk+AUT6ofsHtPk5QyjAdUkpMJ+/Em+quwz4HOt30AQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "clsx": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", + "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", + "dev": true + } + } + }, + "@devtools-ds/tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@devtools-ds/tree/-/tree-1.2.0.tgz", + "integrity": "sha512-hC4g4ocuo2eg7jsnzKdauxH0sDQiPW3KSM2+uK3kRgcmr9PzpBD5Kob+Y/WFSVKswFleftOGKL4BQLuRv0sPxA==", + "dev": true, + "requires": { + "@babel/runtime": "7.7.2", + "@devtools-ds/themes": "^1.2.0", + "clsx": "1.1.0" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.2.tgz", + "integrity": "sha512-JONRbXbTXc9WQE2mAZd1p0Z3DZ/6vaQIkgYMSTP3KjRCyd7rCZCcfhCyX+YjwcKxcZ82UrxbRD358bpExNgrjw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.2" + } + }, + "clsx": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", + "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", + "dev": true + } + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "@eslint/eslintrc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz", + "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "@fortawesome/fontawesome-common-types": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz", + "integrity": "sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz", + "integrity": "sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.1.2" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.2.tgz", + "integrity": "sha512-lTgZz+cMpzjkHmCwOG3E1ilUZrnINYdqMmrkv30EC3XbRsGlbIOL8H9LaNp5SV4g0pNJDfQ4EdTWWaMvdwyLiQ==", + "requires": { + "@fortawesome/fontawesome-common-types": "6.1.2" + } + }, + "@fortawesome/react-fontawesome": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", + "requires": { + "prop-types": "^15.8.1" + } + }, + "@fullcalendar/core": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-4.4.2.tgz", + "integrity": "sha512-vq7KQGuAJ1ieFG5tUqwxwUwmXYtblFOTjHaLAVHo6iEPB52mS7DS45VJfkhaQmX4+5/+BHRpg82G1qkuAINwtg==" + }, + "@fullcalendar/daygrid": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/daygrid/-/daygrid-4.4.2.tgz", + "integrity": "sha512-axjfMhxEXHShV3r2TZjf+2niJ1C6LdAxkHKmg7mVq4jXtUQHOldU5XsjV0v2lUAt1urJBFi2zajfK8798ukL3Q==" + }, + "@fullcalendar/interaction": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/interaction/-/interaction-4.4.2.tgz", + "integrity": "sha512-3ItpGFnxcYQT4NClqhq93QTQwOI8x3mlMf5M4DgK5avVaSzpv9g8p+opqeotK2yzpFeINps06cuQyB1h7vcv1Q==" + }, + "@fullcalendar/list": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-4.4.2.tgz", + "integrity": "sha512-buhfd0w0PavH3EVZ6DR6kvjb+wPDe16XEpNcPkTpvIxnAziwGBvcUeHUBd9KvtEhOcvs9sAKoYKbU4xwHFK0Wg==" + }, + "@fullcalendar/moment": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/moment/-/moment-4.4.2.tgz", + "integrity": "sha512-PBrjxxDEG3RO+8SOA3a1YA7yoGI3bgnltiGY3ehOtJwFIMsUQDSSr5aMoWyRpz7MXgp2YOQY5rzMEIp2A8eK9w==" + }, + "@fullcalendar/moment-timezone": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/moment-timezone/-/moment-timezone-4.4.2.tgz", + "integrity": "sha512-8CjGpBdrQqDh60y6BQJScR2OcCNghPrMFNXd5L9PkU6ktfoYJapTyPZNddCXPPFiPJJdEmarU+RxPxgkl/EP9g==" + }, + "@fullcalendar/react": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/react/-/react-4.4.2.tgz", + "integrity": "sha512-CObyC53Ph2wer83XOm2ae7gEDP5YuENbycetnKgXPLrUVx94hxJGo+G8lZFI4LeUG1nkecfNCpazoa3+x0yKsQ==", + "requires": { + "@fullcalendar/core": "~4.4.0", + "fast-deep-equal": "^2.0.1" + } + }, + "@fullcalendar/timegrid": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@fullcalendar/timegrid/-/timegrid-4.4.2.tgz", + "integrity": "sha512-M5an7qii8OUmI4ogY47k5pn2j/qUbLp6sa6Vo0gO182HR5pb9YtrEZnoQhnScok+I0BkDkLFzMQoiAMTjBm2PQ==", + "requires": { + "@fullcalendar/daygrid": "~4.4.0" + } + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" + }, + "@hapi/address": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz", + "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==" + }, + "@hapi/bourne": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz", + "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==" + }, + "@hapi/hoek": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz", + "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==" + }, + "@hapi/joi": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz", + "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==", + "requires": { + "@hapi/address": "2.x.x", + "@hapi/bourne": "1.x.x", + "@hapi/hoek": "8.x.x", + "@hapi/topo": "3.x.x" + } + }, + "@hapi/topo": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz", + "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==", + "requires": { + "@hapi/hoek": "^8.3.0" + } + }, + "@headlessui/react": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz", + "integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==" + }, + "@heroicons/react": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-1.0.6.tgz", + "integrity": "sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==" + }, + "@humanwhocodes/config-array": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", + "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==" + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "@iconscout/react-unicons": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@iconscout/react-unicons/-/react-unicons-1.1.6.tgz", + "integrity": "sha512-BnyVvBew7Vm1lvL8+qyqjchUbkVHlDyNAlN+r5b+0P0KrkQ66BHPBuJEJ2faT89L8qRu+TohE7dHMV+bndje3Q==", + "requires": { + "react": ">=15.0.0 <17.0.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "requires": { + "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" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" + }, + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", + "requires": { + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + } + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "dependencies": { + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "@jest/schemas": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", + "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", + "requires": { + "@sinclair/typebox": "^0.24.1" + } + }, + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + "requires": { + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "@material-ui/core": { + "version": "4.12.4", + "resolved": "https://registry.npmjs.org/@material-ui/core/-/core-4.12.4.tgz", + "integrity": "sha512-tr7xekNlM9LjA6pagJmL8QCgZXaubWUwkJnoYcMKd4gw/t4XiyvnTkjdGrUVicyB2BsdaAv1tvow45bPM4sSwQ==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/styles": "^4.11.5", + "@material-ui/system": "^4.12.2", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "@types/react-transition-group": "^4.2.0", + "clsx": "^1.0.4", + "hoist-non-react-statics": "^3.3.2", + "popper.js": "1.16.1-lts", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0", + "react-transition-group": "^4.4.0" + } + }, + "@material-ui/icons": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.3.tgz", + "integrity": "sha512-IKHlyx6LDh8n19vzwH5RtHIOHl9Tu90aAAxcbWME6kp4dmvODM3UvOHJeMIDzUbd4muuJKHmlNoBN+mDY4XkBA==", + "requires": { + "@babel/runtime": "^7.4.4" + } + }, + "@material-ui/styles": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.5.tgz", + "integrity": "sha512-o/41ot5JJiUsIETME9wVLAJrmIWL3j0R0Bj2kCOLbSfqEkKf0fmaPt+5vtblUh5eXr2S+J/8J3DaCb10+CzPGA==", + "requires": { + "@babel/runtime": "^7.4.4", + "@emotion/hash": "^0.8.0", + "@material-ui/types": "5.1.0", + "@material-ui/utils": "^4.11.3", + "clsx": "^1.0.4", + "csstype": "^2.5.2", + "hoist-non-react-statics": "^3.3.2", + "jss": "^10.5.1", + "jss-plugin-camel-case": "^10.5.1", + "jss-plugin-default-unit": "^10.5.1", + "jss-plugin-global": "^10.5.1", + "jss-plugin-nested": "^10.5.1", + "jss-plugin-props-sort": "^10.5.1", + "jss-plugin-rule-value-function": "^10.5.1", + "jss-plugin-vendor-prefixer": "^10.5.1", + "prop-types": "^15.7.2" + } + }, + "@material-ui/system": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@material-ui/system/-/system-4.12.2.tgz", + "integrity": "sha512-6CSKu2MtmiJgcCGf6nBQpM8fLkuB9F55EKfbdTC80NND5wpTmKzwdhLYLH3zL4cLlK0gVaaltW7/wMuyTnN0Lw==", + "requires": { + "@babel/runtime": "^7.4.4", + "@material-ui/utils": "^4.11.3", + "csstype": "^2.5.2", + "prop-types": "^15.7.2" + } + }, + "@material-ui/types": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@material-ui/types/-/types-5.1.0.tgz", + "integrity": "sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A==" + }, + "@material-ui/utils": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@material-ui/utils/-/utils-4.11.3.tgz", + "integrity": "sha512-ZuQPV4rBK/V1j2dIkSSEcH5uT6AaHuKWFfotADHsC0wVL1NLd2WkFCm4ZZbX33iO4ydl6V0GPngKm8HZQ2oujg==", + "requires": { + "@babel/runtime": "^7.4.4", + "prop-types": "^15.7.2", + "react-is": "^16.8.0 || ^17.0.0" + } + }, + "@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "dev": true, + "requires": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "dev": true + }, + "@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", + "dev": true + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "dependencies": { + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "@paralleldrive/feature-toggles": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@paralleldrive/feature-toggles/-/feature-toggles-1.0.4.tgz", + "integrity": "sha512-TFKftasIaymFv7ZUWvdyZDSbaxYzhDH6hP5Rv+zfMThZxEsJqaVbw5oToyh1Y+A439f2z2XRHVUF/0lEKKGbVQ==", + "requires": { + "lodash": "4.17.11", + "ramda": "0.26.1", + "url-parse": "1.4.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "url-parse": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + } + } + }, + "@paralleldrive/react-feature-toggles": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/react-feature-toggles/-/react-feature-toggles-2.3.1.tgz", + "integrity": "sha512-GJbpD2R+h2s1SjlZgFGSlAMHSMJLJYuGk/0GMiVzubOchOun/dIZXp8HqYvNXvr4yOFU4Ocsgd8BgribBZIGrw==" + }, + "@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz", + "integrity": "sha512-bcKCAzF0DV2IIROp9ZHkRJa6O4jy7NlnHdWL3GmcUxYWNjLXkK5kfELELwEfSP5hXPfVL/qOGMAROuMQb9GG8Q==", + "requires": { + "ansi-html-community": "^0.0.8", + "common-path-prefix": "^3.0.0", + "core-js-pure": "^3.8.1", + "error-stack-parser": "^2.0.6", + "find-up": "^5.0.0", + "html-entities": "^2.1.0", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + } + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + } + } + }, + "@rushstack/eslint-patch": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz", + "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==" + }, + "@sentry/browser": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.30.0.tgz", + "integrity": "sha512-rOb58ZNVJWh1VuMuBG1mL9r54nZqKeaIlwSlvzJfc89vyfd7n6tQ1UXMN383QBz/MS5H5z44Hy5eE+7pCrYAfw==", + "requires": { + "@sentry/core": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/core": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", + "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "requires": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/hub": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", + "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "requires": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "requires": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==" + }, + "@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "requires": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + } + }, + "@sheerun/mutationobserver-shim": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz", + "integrity": "sha512-DetpxZw1fzPD5xUBrIAoplLChO2VB8DlL5Gg+I1IR9b2wPqYIca2WSUxL5g1vLeR4MsQq1NeWriXAVffV+U1Fw==" + }, + "@sinclair/typebox": { + "version": "0.24.28", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.28.tgz", + "integrity": "sha512-dgJd3HLOkLmz4Bw50eZx/zJwtBq65nms3N9VBYu5LTjJ883oBFkTyXRlCB/ZGGwqYpJJHA5zW2Ibhl5ngITfow==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@storybook/addon-actions": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.5.10.tgz", + "integrity": "sha512-vpCnEu81fmtYzOf0QsRYoDuf9wXgVVl2VysE1dWRebRhIUDU0JurrthTnw322e38D4FzaoNGqZE7wnBYBohzZA==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "polished": "^4.2.2", + "prop-types": "^15.7.2", + "react-inspector": "^5.1.0", + "regenerator-runtime": "^0.13.7", + "telejson": "^6.0.8", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "uuid-browser": "^3.1.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "@storybook/addon-backgrounds": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.5.10.tgz", + "integrity": "sha512-5uzQda3dh891h7BL8e9Ymk7BI+QgkkzDJXuA4mHjOXfIiD3S3efhJI8amXuBC2ZpIr6zmVit0MqZVyoVve46cQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-controls": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.5.10.tgz", + "integrity": "sha512-lC2y3XcolmQAJwFurIyGrynAHPWmfNtTCdu3rQBTVGwyxCoNwdOOeC2jV0BRqX2+CW6OHzJr9frNWXPSaZ8c4w==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/node-logger": "6.5.10", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-docs": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.5.10.tgz", + "integrity": "sha512-1kgjo3f0vL6GN8fTwLL05M/q/kDdzvuqwhxPY/v5hubFb3aQZGr2yk9pRBaLAbs4bez0yG0ASXcwhYnrEZUppg==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@jest/transform": "^26.6.2", + "@mdx-js/react": "^1.6.22", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/docs-tools": "6.5.10", + "@storybook/mdx1-csf": "^0.0.1", + "@storybook/node-logger": "6.5.10", + "@storybook/postinstall": "6.5.10", + "@storybook/preview-web": "6.5.10", + "@storybook/source-loader": "6.5.10", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "babel-loader": "^8.0.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "regenerator-runtime": "^0.13.7", + "remark-external-links": "^8.0.0", + "remark-slug": "^6.0.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true + }, + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "@storybook/addon-essentials": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.5.10.tgz", + "integrity": "sha512-PT2aiR4vgAyB0pl3HNBUa4/a7NDRxASxAazz7zt9ZDirkipDKfxwdcLeRoJzwSngVDWEhuz5/paN5x4eNp4Hww==", + "dev": true, + "requires": { + "@storybook/addon-actions": "6.5.10", + "@storybook/addon-backgrounds": "6.5.10", + "@storybook/addon-controls": "6.5.10", + "@storybook/addon-docs": "6.5.10", + "@storybook/addon-measure": "6.5.10", + "@storybook/addon-outline": "6.5.10", + "@storybook/addon-toolbars": "6.5.10", + "@storybook/addon-viewport": "6.5.10", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/node-logger": "6.5.10", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-interactions": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-6.5.10.tgz", + "integrity": "sha512-+O/ZuQjonpFmTdFRqjCimQTx4S4c1+S3dYCn6gD/E4xzqlQn1BQaER3paX/aBUKb3oRaSO9RUQ+uxePM4zBEwA==", + "dev": true, + "requires": { + "@devtools-ds/object-inspector": "^1.1.2", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/instrumenter": "6.5.10", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0", + "jest-mock": "^27.0.6", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@storybook/addon-links": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.5.10.tgz", + "integrity": "sha512-r3WzYIPz7WjHiaPObC2Tg6bHuZRBb/Kt/X+Eitw+jTqBel7ksvkO36tn81q8Eyj61qIdNQmUWAaX/0aewT0kLA==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/router": "6.5.10", + "@types/qs": "^6.9.5", + "core-js": "^3.8.2", + "global": "^4.4.0", + "prop-types": "^15.7.2", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/addon-measure": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.5.10.tgz", + "integrity": "sha512-ss7L1H5K5hXygDIoVwj+QyVXbve5V67x7CofLiLCgQYuJzfO16+sPGjiTGWMpTb4ijox2uKWnTkpilt5bCjXgw==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "core-js": "^3.8.2", + "global": "^4.4.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-outline": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.5.10.tgz", + "integrity": "sha512-AjdaeQ+/iBKmGrAqRW4niwMB6AkgGnYmSzVs5Cf6F/Sb4Dp+vzgLNOwLABD9qs8Ri8dvHl5J4QpVwQKUhYZaOQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-postcss": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@storybook/addon-postcss/-/addon-postcss-2.0.0.tgz", + "integrity": "sha512-Nt82A7e9zJH4+A+VzLKKswUfru+T6FJTakj4dccP0i8DSn7a0CkzRPrLuZBq8tg4voV6gD74bcDf3gViCVBGtA==", + "dev": true, + "requires": { + "@storybook/node-logger": "^6.1.14", + "css-loader": "^3.6.0", + "postcss": "^7.0.35", + "postcss-loader": "^4.2.0", + "style-loader": "^1.3.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + } + } + }, + "@storybook/addon-toolbars": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.5.10.tgz", + "integrity": "sha512-S0Ljc6Wv+bPbx2e0iTveJ6bBDqjsemu+FZD4qDLsHreoI7DAcqyrF5Def1l8xNohixIVpx8dQpYXRtyzNlXekg==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addon-viewport": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.5.10.tgz", + "integrity": "sha512-RFMd+4kZljyuJjR9OJ2bFXHrSG7VTi5FDZYWEU+4W1sBxzC+JhnVnUP+HJH3gUxEFIRQC5neRzwWRE9RUUoALQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "prop-types": "^15.7.2", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/addons": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.10.tgz", + "integrity": "sha512-VD4tBCQ23PkSeDoxuHcKy0RfhIs3oMYjBacOZx7d0bvOzK9WjPyvE2ysDAh7r/ceqnwmWHAScIpE+I1RU7gl+g==", + "dev": true, + "requires": { + "@storybook/api": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/router": "6.5.10", + "@storybook/theming": "6.5.10", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/api": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.10.tgz", + "integrity": "sha512-AkmgSPNEGdKp4oZA4KQ+RJsacw7GwfvjsVDnCkcXqS9zmSr/RNL0fhpcd60KKkmx/hGKPTDFpK3ZayxDrJ/h4A==", + "dev": true, + "requires": { + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "telejson": "^6.0.8", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + } + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + } + } + }, + "@storybook/builder-webpack4": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.5.10.tgz", + "integrity": "sha512-AoKjsCNoQQoZXYwBDxO8s+yVEd5FjBJAaysEuUTHq2fb81jwLrGcEOo6hjw4jqfugZQIzYUEjPazlvubS78zpw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/preview-web": "6.5.10", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "@storybook/ui": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "@types/webpack": "^4.41.26", + "autoprefixer": "^9.8.6", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "file-loader": "^6.2.0", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "global": "^4.4.0", + "html-webpack-plugin": "^4.0.0", + "pnp-webpack-plugin": "1.6.4", + "postcss": "^7.0.36", + "postcss-flexbugs-fixes": "^4.2.1", + "postcss-loader": "^4.2.0", + "raw-loader": "^4.0.2", + "stable": "^0.1.8", + "style-loader": "^1.3.0", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-filter-warnings-plugin": "^1.2.1", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.2.2" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz", + "integrity": "sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==", + "dev": true, + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/builder-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-6.5.10.tgz", + "integrity": "sha512-Hcsm/TzGRXHndgQCftt+pzI7GQJRqAv8A8ie5b3aFcodhJfK0qzZsQD4Y4ZWxXh1I/xe5t74Kl2qUJ40PX+geA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/preview-web": "6.5.10", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@storybook/theming": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-named-exports-order": "^0.0.2", + "browser-assert": "^1.2.1", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "html-webpack-plugin": "^5.0.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stable": "^0.1.8", + "style-loader": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "clean-css": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", + "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + } + } + }, + "@storybook/channel-postmessage": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.5.10.tgz", + "integrity": "sha512-t9PTA0UzFvYa3IlOfpBOolfrRMPTjUMIeCQ6FNyM0aj5GqLKSvoQzP8NeoRpIrvyf6ljFKKdaMaZ3fiCvh45ag==", + "dev": true, + "requires": { + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0", + "qs": "^6.10.0", + "telejson": "^6.0.8" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/channel-websocket": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.5.10.tgz", + "integrity": "sha512-RTXMZbMWCS3xU+4GVIdfnUXsKcwg/WTozy88/5OxaKjGw6KgRedqLAQJKJ6Y5XlnwIcWelirkHj/COwTTXhbPg==", + "dev": true, + "requires": { + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0", + "telejson": "^6.0.8" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/channels": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.10.tgz", + "integrity": "sha512-lo26YZ6kWpHXLhuHJF4P/bICY7jD/rXEZqReKtGOSk1Lv99/xvG6pqmcy3hWLf3v3Dy/8otjRPSR7izFVIIZgQ==", + "dev": true, + "requires": { + "core-js": "^3.8.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/cli": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-6.5.10.tgz", + "integrity": "sha512-avxlWVaxMasP4svsYaJ6ELfrcP3SKaIJeFbiu688kQCCX+7pOUOaWPXfiScNpuoQ8wdghcwyZzRkhcV873rHHA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/preset-env": "^7.12.11", + "@storybook/codemod": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/csf-tools": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/telemetry": "6.5.10", + "boxen": "^5.1.2", + "chalk": "^4.1.0", + "commander": "^6.2.1", + "core-js": "^3.8.2", + "cross-spawn": "^7.0.3", + "envinfo": "^7.7.3", + "express": "^4.17.1", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "get-port": "^5.1.1", + "globby": "^11.0.2", + "jscodeshift": "^0.13.1", + "json5": "^2.1.3", + "leven": "^3.1.0", + "prompts": "^2.4.0", + "puppeteer-core": "^2.1.1", + "read-pkg-up": "^7.0.1", + "shelljs": "^0.8.5", + "strip-json-comments": "^3.0.1", + "ts-dedent": "^2.0.0", + "update-notifier": "^5.0.1" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@storybook/client-api": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.5.10.tgz", + "integrity": "sha512-3wBWZl3NvMFgMovgEh+euiARAT2FXzpvTF4Q1gerGMNNDlrGxHnFvSuy4FHg/irtOGLa4yLz43ULFbYtpKw0Lg==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/store": "6.5.10", + "@types/qs": "^6.9.5", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/client-logger": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.10.tgz", + "integrity": "sha512-/xA0MHOevXev68hyLMQw8Qo8KczSIdXOxliAgrycMTkDmw5eKeA8TP7B8zP3wGuq/e3MrdD9/8MWhb/IQBNC3w==", + "dev": true, + "requires": { + "core-js": "^3.8.2", + "global": "^4.4.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/codemod": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-6.5.10.tgz", + "integrity": "sha512-fE/5qMHlv54VU2dQyZljFGCEcoFWS2kL3i5bvuf1Ha0HnyZ0gNOXzwBGqCjzxC5RE1Oz3Z6Dy1ZT98Q4LP4lZg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.11", + "@mdx-js/mdx": "^1.6.22", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/csf-tools": "6.5.10", + "@storybook/node-logger": "6.5.10", + "core-js": "^3.8.2", + "cross-spawn": "^7.0.3", + "globby": "^11.0.2", + "jscodeshift": "^0.13.1", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "recast": "^0.19.0", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + } + } + }, + "@storybook/components": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.10.tgz", + "integrity": "sha512-9OhgB8YQfGwOKjo/N96N5mrtJ6qDVVoEM1zuhea32tJUd2eYf0aSWpryA9VnOM0V1q/8DAoCg5rPBMYWMBU5uw==", + "dev": true, + "requires": { + "@storybook/client-logger": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/core": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.5.10.tgz", + "integrity": "sha512-K86yYa0tYlMxADlwQTculYvPROokQau09SCVqpsLg3wJCTvYFL4+SIqcYoyBSbFmHOdnYbJgPydjN33MYLiOZQ==", + "dev": true, + "requires": { + "@storybook/core-client": "6.5.10", + "@storybook/core-server": "6.5.10" + } + }, + "@storybook/core-client": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.5.10.tgz", + "integrity": "sha512-THsIjNrOrampTl0Lgfjvfjk1JnktKb4CQLOM80KpQb4cjDqorBjJmErzUkUQ2y3fXvrDmQ/kUREkShET4XEdtA==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/channel-websocket": "6.5.10", + "@storybook/client-api": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/preview-web": "6.5.10", + "@storybook/store": "6.5.10", + "@storybook/ui": "6.5.10", + "airbnb-js-shims": "^2.2.1", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/core-common": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.5.10.tgz", + "integrity": "sha512-Bx+VKkfWdrAmD8T51Sjq/mMhRaiapBHcpG4cU5bc3DMbg+LF2/yrgqv/cjVu+m5gHAzYCac5D7gqzBgvG7Myww==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-proposal-private-property-in-object": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@babel/register": "^7.12.1", + "@storybook/node-logger": "6.5.10", + "@storybook/semver": "^7.3.2", + "@types/node": "^14.0.10 || ^16.0.0", + "@types/pretty-hrtime": "^1.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^3.0.1", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "handlebars": "^4.7.7", + "interpret": "^2.2.0", + "json5": "^2.1.3", + "lazy-universal-dotenv": "^3.0.1", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "telejson": "^6.0.8", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "4" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.10.tgz", + "integrity": "sha512-wdGTwWF5QtpTY/gbBtQLAiCnoxfD4qMbN87NYZle1dOZ9Os8Y6zXcKrIaOU8W+TIvFUWVGG9tUgNww3CjXRVVw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.18.6" + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/core-events": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.10.tgz", + "integrity": "sha512-EVb1gO1172klVIAABLOoigFMx0V88uctY0K/qVCO8n6v+wd2+0Ccn63kl+gTxsAC3WZ8XhXh9q2w5ImHklVECw==", + "dev": true, + "requires": { + "core-js": "^3.8.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/core-server": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.5.10.tgz", + "integrity": "sha512-jqwpA0ccA8X5ck4esWBid04+cEIVqirdAcqJeNb9IZAD+bRreO4Im8ilzr7jc5AmQ9fkqHs2NByFKh9TITp8NQ==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-webpack4": "6.5.10", + "@storybook/core-client": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/csf-tools": "6.5.10", + "@storybook/manager-webpack4": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@storybook/telemetry": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "@types/node-fetch": "^2.5.7", + "@types/pretty-hrtime": "^1.0.0", + "@types/webpack": "^4.41.26", + "better-opn": "^2.1.1", + "boxen": "^5.1.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "commander": "^6.2.1", + "compression": "^1.7.4", + "core-js": "^3.8.2", + "cpy": "^8.1.2", + "detect-port": "^1.3.0", + "express": "^4.17.1", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "globby": "^11.0.2", + "ip": "^2.0.0", + "lodash": "^4.17.21", + "node-fetch": "^2.6.7", + "open": "^8.4.0", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "regenerator-runtime": "^0.13.7", + "serve-favicon": "^2.5.0", + "slash": "^3.0.0", + "telejson": "^6.0.8", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "webpack": "4", + "ws": "^8.2.3", + "x-default-browser": "^0.4.0" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + } + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + } + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + } + } + }, + "ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/csf": { + "version": "0.0.2--canary.4566f4d.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2--canary.4566f4d.1.tgz", + "integrity": "sha512-9OVvMVh3t9znYZwb0Svf/YQoxX2gVOeQTGe2bses2yj+a3+OJnCrUF3/hGv6Em7KujtOdL2LL+JnG49oMVGFgQ==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "@storybook/csf-tools": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.5.10.tgz", + "integrity": "sha512-H77kZQEisu7+skzeIbNZwmE09OqLjwJTeFhLN1pcjxKVa30LEI3pBHcNBxVKqgxl+Yg3KkB7W/ArLO2N+i2ohw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@babel/traverse": "^7.12.11", + "@babel/types": "^7.12.11", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/mdx1-csf": "^0.0.1", + "core-js": "^3.8.2", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@storybook/docs-tools": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-6.5.10.tgz", + "integrity": "sha512-/bvYgOO+CxMEcHifkjJg0A60OTGOhcjGxnsB1h0gJuxMrqA/7Qwc108bFmPiX0eiD1BovFkZLJV4O6OY7zP5Vw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/store": "6.5.10", + "core-js": "^3.8.2", + "doctrine": "^3.0.0", + "lodash": "^4.17.21", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/instrumenter": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.10.tgz", + "integrity": "sha512-3yKJW68wTnGYEts2mJQG6M7ZE+fe54fuy5lBBzRtvWnC15uWTxuaiFp2kxH5b+stSCi4m71ws45RNiEafdBgEQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "core-js": "^3.8.2", + "global": "^4.4.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/manager-webpack4": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.5.10.tgz", + "integrity": "sha512-N/TlNDhuhARuFipR/ZJ/xEVESz23iIbCsZ4VNehLHm8PpiGlQUehk+jMjWmz5XV0bJItwjRclY+CU3GjZKblfQ==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/core-client": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/theming": "6.5.10", + "@storybook/ui": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "@types/webpack": "^4.41.26", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "express": "^4.17.1", + "file-loader": "^6.2.0", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^4.0.0", + "node-fetch": "^2.6.7", + "pnp-webpack-plugin": "1.6.4", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^1.3.0", + "telejson": "^6.0.8", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-virtual-modules": "^0.2.2" + }, + "dependencies": { + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz", + "integrity": "sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==", + "dev": true, + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/manager-webpack5": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.5.10.tgz", + "integrity": "sha512-uRo+6e5MiVOtyFVMYIKVqvpDveCjHyzXBfetSYR7rKEZoaDMEnLLiuF7DIH12lzxwmzCJ1gIc4lf5HFiTMNkgw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.5.10", + "@storybook/core-client": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/theming": "6.5.10", + "@storybook/ui": "6.5.10", + "@types/node": "^14.0.10 || ^16.0.0", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "express": "^4.17.1", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^5.0.0", + "node-fetch": "^2.6.7", + "process": "^0.11.10", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^2.0.0", + "telejson": "^6.0.8", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "clean-css": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", + "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + } + } + }, + "@storybook/mdx1-csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", + "integrity": "sha512-4biZIWWzoWlCarMZmTpqcJNgo/RBesYZwGFbQeXiGYsswuvfWARZnW9RE9aUEMZ4XPn7B1N3EKkWcdcWe/K2tg==", + "dev": true, + "requires": { + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/preset-env": "^7.12.11", + "@babel/types": "^7.12.11", + "@mdx-js/mdx": "^1.6.22", + "@types/lodash": "^4.14.167", + "js-string-escape": "^1.0.1", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + } + } + }, + "@storybook/node-logger": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.10.tgz", + "integrity": "sha512-bYswXIKV7Stru8vYfkjUMNN8UhF7Qg7NRsUvG5Djt5lLIae1XmUIgnH40mU/nW4X4BSfcR9MKxsSsngvn2WmQg==", + "dev": true, + "requires": { + "@types/npmlog": "^4.1.2", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "npmlog": "^5.0.1", + "pretty-hrtime": "^1.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@storybook/postinstall": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.5.10.tgz", + "integrity": "sha512-xqUdpnFHYkn8MgtV+QztvIsRWa6jQUk7QT1Mu17Y0S7PbslNGsuskRPHenHhACXBJF+TM86R+4BaAhnVYTmElw==", + "dev": true, + "requires": { + "core-js": "^3.8.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/preset-create-react-app": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@storybook/preset-create-react-app/-/preset-create-react-app-4.1.2.tgz", + "integrity": "sha512-5uBZPhuyXx4APgLZnhiZ/PqYYprBua5CabQCfAlk+/9V4vSpX+ww+XP4Rl8Ifc/nf/HktgwtJFH4HXrZGRKC4w==", + "dev": true, + "requires": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1", + "@storybook/react-docgen-typescript-plugin": "^1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", + "@types/babel__core": "^7.1.7", + "babel-plugin-react-docgen": "^4.1.0", + "pnp-webpack-plugin": "^1.7.0", + "semver": "^7.3.5" + }, + "dependencies": { + "pnp-webpack-plugin": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz", + "integrity": "sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==", + "dev": true, + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@storybook/preview-web": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.5.10.tgz", + "integrity": "sha512-sTC/o5gkvALOtcNgtApGKGN9EavvSxRHBeBh+5BQjV2qQ8ap+26RsfUizNBECAa2Jrn4osaDYn9HRhJLFL69WA==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/channel-postmessage": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/store": "6.5.10", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/react": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-6.5.10.tgz", + "integrity": "sha512-m8S1qQrwA7pDGwdKEvL6LV3YKvSzVUY297Fq+xcTU3irnAy4sHDuFoLqV6Mi1510mErK1r8+rf+0R5rEXB219g==", + "dev": true, + "requires": { + "@babel/preset-flow": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@storybook/addons": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core": "6.5.10", + "@storybook/core-common": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "@storybook/docs-tools": "6.5.10", + "@storybook/node-logger": "6.5.10", + "@storybook/react-docgen-typescript-plugin": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.5.10", + "@types/estree": "^0.0.51", + "@types/node": "^14.14.20 || ^16.0.0", + "@types/webpack-env": "^1.16.0", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "babel-plugin-add-react-displayname": "^0.0.5", + "babel-plugin-react-docgen": "^4.2.1", + "core-js": "^3.8.2", + "escodegen": "^2.0.0", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "html-tags": "^3.1.0", + "lodash": "^4.17.21", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^14.3.4", + "react-refresh": "^0.11.0", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": ">=4.43.0 <6.0.0" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "@types/node": { + "version": "16.11.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.56.tgz", + "integrity": "sha512-aFcUkv7EddxxOa/9f74DINReQ/celqH8DiB3fRYgVDM2Xm5QJL8sl80QKuAnGvwAsMn+H3IFA6WCrQh1CY7m1A==", + "dev": true + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@storybook/react-docgen-typescript-plugin": { + "version": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0.tgz", + "integrity": "sha512-eVg3BxlOm2P+chijHBTByr90IZVUtgRW56qEOLX7xlww2NBuKrcavBlcmn+HH7GIUktquWkMPtvy6e0W0NgA5w==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^2.1.1", + "tslib": "^2.0.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "@storybook/router": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.10.tgz", + "integrity": "sha512-O+vNW/eEpYFF8eCg5jZjNQ6q2DKQVxqDRPCy9pJdEbvavMDZn6AFYgVK+VJe5F4211WW2yncOu922xObCxXJYg==", + "dev": true, + "requires": { + "@storybook/client-logger": "6.5.10", + "core-js": "^3.8.2", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@storybook/source-loader": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.5.10.tgz", + "integrity": "sha512-1RxxRumpjs8VUUwES9LId+cuNQnixhZAcwCxd6jaKkTZbjiQCtAhXX6DBTjJGV1u/JnCsqEp5b1wB8j/EioNHw==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "core-js": "^3.8.2", + "estraverse": "^5.2.0", + "global": "^4.4.0", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + } + } + }, + "@storybook/store": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.5.10.tgz", + "integrity": "sha512-RswrSYh2IiKkytFPxP9AvP+hekjrvHK2ILvyDk2ZgduCN4n5ivsekOb+N3M2t+dq1eLuW9or5n2T4OWwAwjxxQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/csf": "0.0.2--canary.4566f4d.1", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "slash": "^3.0.0", + "stable": "^0.1.8", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "@storybook/telemetry": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-6.5.10.tgz", + "integrity": "sha512-+M5HILDFS8nDumLxeSeAwi1MTzIuV6UWzV4yB2wcsEXOBTdplcl9oYqFKtlst78oOIdGtpPYxYfivDlqxC2K4g==", + "dev": true, + "requires": { + "@storybook/client-logger": "6.5.10", + "@storybook/core-common": "6.5.10", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "detect-package-manager": "^2.0.1", + "fetch-retry": "^5.0.2", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "isomorphic-unfetch": "^3.1.0", + "nanoid": "^3.3.1", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@storybook/testing-library": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/@storybook/testing-library/-/testing-library-0.0.13.tgz", + "integrity": "sha512-vRMeIGer4EjJkTgI8sQyK9W431ekPWYCWL//OmSDJ64IT3h7FnW7Xg6p+eqM3oII98/O5pcya5049GxnjaPtxw==", + "dev": true, + "requires": { + "@storybook/client-logger": "^6.4.0", + "@storybook/instrumenter": "^6.4.0", + "@testing-library/dom": "^8.3.0", + "@testing-library/user-event": "^13.2.1", + "ts-dedent": "^2.2.0" + }, + "dependencies": { + "@testing-library/dom": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.17.1.tgz", + "integrity": "sha512-KnH2MnJUzmFNPW6RIKfd+zf2Wue8mEKX0M3cpX6aKl5ZXrJM1/c/Pc8c2xDNYQCnJO48Sm5ITbMXgqTr3h4jxQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + } + }, + "@testing-library/user-event": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", + "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aria-query": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.2.tgz", + "integrity": "sha512-eigU3vhqSO+Z8BKDnVLN/ompjhf3pYzecKXz8+whRy+9gZu8n1TCGfwzQUUPnqdHl9ax1Hr9031orZ+UOEYr7Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "dom-accessibility-api": { + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz", + "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@storybook/theming": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.10.tgz", + "integrity": "sha512-BvTQBBcSEwKKcsVmF+Ol6v0RIQUr+bxP7gb10wtfBd23mZTEFA0C1N5FnZr/dDeiBKG1pvf1UKvoYA731y0BsA==", + "dev": true, + "requires": { + "@storybook/client-logger": "6.5.10", + "core-js": "^3.8.2", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "@storybook/ui": { + "version": "6.5.10", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.5.10.tgz", + "integrity": "sha512-6iaoaRAiTqB1inTw35vao+5hjcDE0Qa0A3a9ZIeNa6yHvpB1k0lO/N/0PMrRdVvySYpXVD1iry4z4QYdo1rU+w==", + "dev": true, + "requires": { + "@storybook/addons": "6.5.10", + "@storybook/api": "6.5.10", + "@storybook/channels": "6.5.10", + "@storybook/client-logger": "6.5.10", + "@storybook/components": "6.5.10", + "@storybook/core-events": "6.5.10", + "@storybook/router": "6.5.10", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.5.10", + "core-js": "^3.8.2", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + } + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@stripe/react-stripe-js": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.10.0.tgz", + "integrity": "sha512-vuIjJUZJ3nyiaGa5z5iyMCzZfGGsgzOOjWjqknbbhkNsewyyginfeky9EZLSz9+iSAsgC9K6MeNOTLKVGcMycQ==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "@stripe/stripe-js": { + "version": "1.35.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.35.0.tgz", + "integrity": "sha512-UIuzpbJqgXCTvJhY/aZYvBtaKdMfQgnIv6kkLlfRJ9smZcC4zoPvq3j7k9wobYI+idHAWP4BRiPnqA8lvzJCtg==" + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-j7KnilGyZzYr/jhcrSYS3FGWMZVaqyCG0vzMCwzvei0coIkczuYMcniK07nI0aHJINciujjH11T72ICW5eL5Ig==" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.2.0.tgz", + "integrity": "sha512-3XHLtJ+HbRCH4n28S7y/yZoEQnRpl0tvTZQsHqvaeNXPra+6vE5tbRliH3ox1yZYPCxrlqaJT/Mg+75GpDKlvQ==" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz", + "integrity": "sha512-yTr2iLdf6oEuUE9MsRdvt0NmdpMBAkgK8Bjhl6epb+eQWk6abBaX3d65UZ3E3FWaOwePyUgNyNCMVG61gGCQ7w==" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz", + "integrity": "sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w==" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.3.3.tgz", + "integrity": "sha512-w3Be6xUNdwgParsvxkkeZb545VhXEwjGMwExMVBIdPQJeyMQHqm9Msnb2a1teHBqUYL66qtwfhNkbj1iarCG7w==" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.2.0.tgz", + "integrity": "sha512-C0Uy+BHolCHGOZ8Dnr1zXy/KgpBOkEUYY9kI/HseHVPeMbluaX3CijJr7D4C5uR8zrc1T64nnq/k63ydQuGt4w==" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.2.0.tgz", + "integrity": "sha512-7YvynOpZDpCOUoIVlaaOUU87J4Z6RdD6spYN4eUb5tfPoKGSF9OG2NuhgYnq4jSkAxcpMaXWPf1cePkzmqTPNw==" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz", + "integrity": "sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw==" + }, + "@svgr/babel-preset": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-4.3.3.tgz", + "integrity": "sha512-6PG80tdz4eAlYUN3g5GZiUjg2FMcp+Wn6rtnz5WJG9ITGEF1pmFdzq02597Hn0OmnQuCVaBYQE1OVFAnwOl+0A==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^4.2.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^4.2.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^4.2.0", + "@svgr/babel-plugin-svg-dynamic-title": "^4.3.3", + "@svgr/babel-plugin-svg-em-dimensions": "^4.2.0", + "@svgr/babel-plugin-transform-react-native-svg": "^4.2.0", + "@svgr/babel-plugin-transform-svg-component": "^4.2.0" + } + }, + "@svgr/core": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-4.3.3.tgz", + "integrity": "sha512-qNuGF1QON1626UCaZamWt5yedpgOytvLj5BQZe2j1k1B8DUG4OyugZyfEwBeXozCUwhLEpsrgPrE+eCu4fY17w==", + "requires": { + "@svgr/plugin-jsx": "^4.3.3", + "camelcase": "^5.3.1", + "cosmiconfig": "^5.2.1" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" + } + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.3.2.tgz", + "integrity": "sha512-JioXclZGhFIDL3ddn4Kiq8qEqYM2PyDKV0aYno8+IXTLuYt6TOgHUbUAAFvqtb0Xn37NwP0BTHglejFoYr8RZg==", + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@svgr/plugin-jsx": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-4.3.3.tgz", + "integrity": "sha512-cLOCSpNWQnDB1/v+SUENHH7a0XY09bfuMKdq9+gYvtuwzC2rU4I0wKGFEp1i24holdQdwodCtDQdFtJiTCWc+w==", + "requires": { + "@babel/core": "^7.4.5", + "@svgr/babel-preset": "^4.3.3", + "@svgr/hast-util-to-babel-ast": "^4.3.2", + "svg-parser": "^2.0.0" + } + }, + "@svgr/plugin-svgo": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz", + "integrity": "sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w==", + "requires": { + "cosmiconfig": "^5.2.1", + "merge-deep": "^3.0.2", + "svgo": "^1.2.2" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" + } + } + }, + "@svgr/webpack": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.3.tgz", + "integrity": "sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg==", + "requires": { + "@babel/core": "^7.4.5", + "@babel/plugin-transform-react-constant-elements": "^7.0.0", + "@babel/preset-env": "^7.4.5", + "@babel/preset-react": "^7.0.0", + "@svgr/core": "^4.3.3", + "@svgr/plugin-jsx": "^4.3.3", + "@svgr/plugin-svgo": "^4.3.1", + "loader-utils": "^1.2.3" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tailwindcss/forms": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.2.tgz", + "integrity": "sha512-pSrFeJB6Bg1Mrg9CdQW3+hqZXAKsBrSG9MAfFLKy1pVA4Mb4W7C0k7mEhlmS2Dfo/otxrQOET7NJiJ9RrS563w==", + "requires": { + "mini-svg-data-uri": "^1.2.3" + } + }, + "@tanem/svg-injector": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/@tanem/svg-injector/-/svg-injector-8.2.5.tgz", + "integrity": "sha512-jQ6UPPY2oSu2d0YLngtvnOIoKheYsB/s2bNP/QdsLrsvlz+PzUUO4RUWBN3+8clZPi2SI5OMF/YoTiTKt5v2xw==", + "requires": { + "@babel/runtime": "^7.12.13", + "content-type": "^1.0.4", + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "@testing-library/dom": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-6.16.0.tgz", + "integrity": "sha512-lBD88ssxqEfz0wFL6MeUyyWZfV/2cjEZZV3YRpb2IoJRej/4f1jB0TzqIOznTpfR1r34CNesrubxwIlAQ8zgPA==", + "requires": { + "@babel/runtime": "^7.8.4", + "@sheerun/mutationobserver-shim": "^0.3.2", + "@types/testing-library__dom": "^6.12.1", + "aria-query": "^4.0.2", + "dom-accessibility-api": "^0.3.0", + "pretty-format": "^25.1.0", + "wait-for-expect": "^3.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/jest-dom": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-4.2.4.tgz", + "integrity": "sha512-j31Bn0rQo12fhCWOUWy9fl7wtqkp7In/YP2p5ZFyRuiiB9Qs3g+hS4gAmDWONbAHcRmVooNJ5eOHQDCOmUFXHg==", + "requires": { + "@babel/runtime": "^7.5.1", + "chalk": "^2.4.1", + "css": "^2.2.3", + "css.escape": "^1.5.1", + "jest-diff": "^24.0.0", + "jest-matcher-utils": "^24.0.0", + "lodash": "^4.17.11", + "pretty-format": "^24.0.0", + "redent": "^3.0.0" + } + }, + "@testing-library/react": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-9.5.0.tgz", + "integrity": "sha512-di1b+D0p+rfeboHO5W7gTVeZDIK5+maEgstrZbWZSSvxDyfDRkkyBE1AJR5Psd6doNldluXlCWqXriUfqu/9Qg==", + "requires": { + "@babel/runtime": "^7.8.4", + "@testing-library/dom": "^6.15.0", + "@types/testing-library__react": "^9.1.2" + } + }, + "@testing-library/user-event": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-7.2.1.tgz", + "integrity": "sha512-oZ0Ib5I4Z2pUEcoo95cT1cr6slco9WY7yiPpG+RGNkj8YcYgJnM7pXmYmorNOReh8MIGcKSqXyeGjxnr8YiZbA==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==" + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, + "@turf/bbox": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-6.5.0.tgz", + "integrity": "sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/meta": "^6.5.0" + } + }, + "@turf/boolean-crosses": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-6.5.0.tgz", + "integrity": "sha512-gvshbTPhAHporTlQwBJqyfW+2yV8q/mOTxG6PzRVl6ARsqNoqYQWkd4MLug7OmAqVyBzLK3201uAeBjxbGw0Ng==", + "requires": { + "@turf/boolean-point-in-polygon": "^6.5.0", + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0", + "@turf/line-intersect": "^6.5.0", + "@turf/polygon-to-line": "^6.5.0" + } + }, + "@turf/boolean-point-in-polygon": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-6.5.0.tgz", + "integrity": "sha512-DtSuVFB26SI+hj0SjrvXowGTUCHlgevPAIsukssW6BG5MlNSBQAo70wpICBNJL6RjukXg8d2eXaAWuD/CqL00A==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0" + } + }, + "@turf/boolean-point-on-line": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-6.5.0.tgz", + "integrity": "sha512-A1BbuQ0LceLHvq7F/P7w3QvfpmZqbmViIUPHdNLvZimFNLo4e6IQunmzbe+8aSStH9QRZm3VOflyvNeXvvpZEQ==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0" + } + }, + "@turf/boolean-within": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-6.5.0.tgz", + "integrity": "sha512-YQB3oU18Inx35C/LU930D36RAVe7LDXk1kWsQ8mLmuqYn9YdPsDQTMTkLJMhoQ8EbN7QTdy333xRQ4MYgToteQ==", + "requires": { + "@turf/bbox": "^6.5.0", + "@turf/boolean-point-in-polygon": "^6.5.0", + "@turf/boolean-point-on-line": "^6.5.0", + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0" + } + }, + "@turf/helpers": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz", + "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==" + }, + "@turf/intersect": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-6.5.0.tgz", + "integrity": "sha512-2legGJeKrfFkzntcd4GouPugoqPUjexPZnOvfez+3SfIMrHvulw8qV8u7pfVyn2Yqs53yoVCEjS5sEpvQ5YRQg==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0", + "polygon-clipping": "^0.15.3" + } + }, + "@turf/invariant": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.5.0.tgz", + "integrity": "sha512-Wv8PRNCtPD31UVbdJE/KVAWKe7l6US+lJItRR/HOEW3eh+U/JwRCSUl/KZ7bmjM/C+zLNoreM2TU6OoLACs4eg==", + "requires": { + "@turf/helpers": "^6.5.0" + } + }, + "@turf/line-intersect": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-6.5.0.tgz", + "integrity": "sha512-CS6R1tZvVQD390G9Ea4pmpM6mJGPWoL82jD46y0q1KSor9s6HupMIo1kY4Ny+AEYQl9jd21V3Scz20eldpbTVA==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0", + "@turf/line-segment": "^6.5.0", + "@turf/meta": "^6.5.0", + "geojson-rbush": "3.x" + } + }, + "@turf/line-segment": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-6.5.0.tgz", + "integrity": "sha512-jI625Ho4jSuJESNq66Mmi290ZJ5pPZiQZruPVpmHkUw257Pew0alMmb6YrqYNnLUuiVVONxAAKXUVeeUGtycfw==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0", + "@turf/meta": "^6.5.0" + } + }, + "@turf/meta": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz", + "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==", + "requires": { + "@turf/helpers": "^6.5.0" + } + }, + "@turf/polygon-to-line": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-6.5.0.tgz", + "integrity": "sha512-5p4n/ij97EIttAq+ewSnKt0ruvuM+LIDzuczSzuHTpq4oS7Oq8yqg5TQ4nzMVuK41r/tALCk7nAoBuw3Su4Gcw==", + "requires": { + "@turf/helpers": "^6.5.0", + "@turf/invariant": "^6.5.0" + } + }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.0.tgz", + "integrity": "sha512-v4Vwdko+pgymgS+A2UIaJru93zQd85vIGWObM5ekZNdXCKtDYqATlEYnWgfo86Q6I1Lh0oXnksDnMU1cwmlPDw==", + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "requires": { + "@types/node": "*" + } + }, + "@types/cheerio": { + "version": "0.22.31", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.31.tgz", + "integrity": "sha512-Kt7Cdjjdi2XWSfrZ53v4Of0wG3ZcmaegFXjMmz9tfNrZSkzzo36G0AL1YqSdcIA78Etjt6E609pt5h1xnQkPUw==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", + "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, + "@types/crypto-js": { + "version": "3.1.47", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-3.1.47.tgz", + "integrity": "sha512-eI6gvpcGHLk3dAuHYnRCAjX+41gMv1nz/VP55wAe5HtmAKDOoPSfr3f6vkMc08ov1S0NsjvUBxDtHHxqQY1LGA==" + }, + "@types/draft-js": { + "version": "0.11.9", + "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.9.tgz", + "integrity": "sha512-cQJBZjjIlGaPA1tOY+wGz2KhlPtAAZOIXpUvGPxPRw5uzZ2tcj8m6Yu1QDV9YgP36+cqE3cUvgkARBzgUiuI/Q==", + "dev": true, + "requires": { + "@types/react": "*", + "immutable": "~3.7.4" + } + }, + "@types/emoji-mart": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/emoji-mart/-/emoji-mart-3.0.9.tgz", + "integrity": "sha512-qdBo/2Y8MXaJ/2spKjDZocuq79GpnOhkwMHnK2GnVFa8WYFgfA+ei6sil3aeWQPCreOKIx9ogPpR5+7MaOqYAA==", + "requires": { + "@types/react": "*" + } + }, + "@types/emojione": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/@types/emojione/-/emojione-2.2.6.tgz", + "integrity": "sha512-2OJGfbqLOFFawMp61cxpJ+QsLA/2LDUdqWb2YMVNP8q/FXSxdkv0hdqm3EcjNfyfcpZ0HjOjMATwXdx/xpTlOA==" + }, + "@types/enzyme": { + "version": "3.10.12", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.12.tgz", + "integrity": "sha512-xryQlOEIe1TduDWAOphR0ihfebKFSWOXpIsk+70JskCfRfW+xALdnJ0r1ZOTo85F9Qsjk6vtlU7edTYHbls9tA==", + "requires": { + "@types/cheerio": "*", + "@types/react": "*" + } + }, + "@types/enzyme-adapter-react-16": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz", + "integrity": "sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg==", + "requires": { + "@types/enzyme": "*" + } + }, + "@types/eslint": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", + "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz", + "integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==" + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.30", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.30.tgz", + "integrity": "sha512-gstzbTWro2/nFed1WXtf+TtrpwxH7Ggs4RLYTLbeVgIkUQOI3WG/JKjgeOU1zXDvezllupjrf8OPIdvTbIaVOQ==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/geojson": { + "version": "7946.0.8", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz", + "integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==" + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "requires": { + "@types/node": "*" + } + }, + "@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==" + }, + "@types/hoist-non-react-statics": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", + "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", + "requires": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "@types/html-minifier-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==" + }, + "@types/http-proxy": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "requires": { + "@types/node": "*" + } + }, + "@types/is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==", + "dev": true + }, + "@types/is-url": { + "version": "1.2.30", + "resolved": "https://registry.npmjs.org/@types/is-url/-/is-url-1.2.30.tgz", + "integrity": "sha512-AnlNFwjzC8XLda5VjRl4ItSd8qp8pSNowvsut0WwQyBWHpOxjxRJm8iO6uETWqEyLdYdb9/1j+Qd9gQ4l5I4fw==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==" + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", + "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "requires": { + "jest-diff": "^24.3.0" + } + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "@types/lodash": { + "version": "4.14.184", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.184.tgz", + "integrity": "sha512-RoZphVtHbxPZizt4IcILciSWiC6dcn+eZ8oX9IWEYfDMcocdd42f7NPI6fQj+6zI8y4E0L7gu2pcZKLGTRaV9Q==" + }, + "@types/markdown-draft-js": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@types/markdown-draft-js/-/markdown-draft-js-2.2.4.tgz", + "integrity": "sha512-sEb5/uYSl12mnBXF5lgycEJZnzy9BtOQYJJW+UP/prdy2fjTIAm4c1MFRUqSunWocPAhcm6BvjLinGb2awtwOA==", + "dev": true, + "requires": { + "@types/draft-js": "*" + } + }, + "@types/mdast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/mime": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", + "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" + }, + "@types/mime-types": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.1.tgz", + "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", + "dev": true + }, + "@types/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-0RJHq5FqDWo17kdHe+SMDJLfxmLaqHbWnqZ6gNKzDvStUlrmx/eKIY17+ifLS1yybo7X86aUshQMlittDOVNnw==", + "dev": true + }, + "@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/npmlog": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", + "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" + }, + "@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", + "dev": true + }, + "@types/prettier": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.0.tgz", + "integrity": "sha512-RI1L7N4JnW5gQw2spvL7Sllfuf1SaHdrZpCHiBlCXjIlufi1SMNnbu2teze3/QE67Fg2tBlH7W+mi4hVNk4p0A==" + }, + "@types/pretty-hrtime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", + "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + }, + "@types/q": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz", + "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==" + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/react": { + "version": "16.14.30", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.30.tgz", + "integrity": "sha512-tG+xGtDDSuIl1l63mN0LnaROAc99knkYyN4YTheE80iPzYvSy0U8LVie+OBZkrgjVrpkQV6bMCkSphPBnVNk6g==", + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + } + } + }, + "@types/react-dom": { + "version": "16.9.16", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.16.tgz", + "integrity": "sha512-Oqc0RY4fggGA3ltEgyPLc3IV9T73IGoWjkONbsyJ3ZBn+UPPCYpU2ec0i3cEbJuEdZtkqcCF2l1zf2pBdgUGSg==", + "requires": { + "@types/react": "^16" + } + }, + "@types/react-redux": { + "version": "7.1.24", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", + "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "@types/react-router": { + "version": "5.1.18", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.18.tgz", + "integrity": "sha512-YYknwy0D0iOwKQgz9v8nOzt2J6l4gouBmDnWqUUznltOTaon+r8US8ky8HvN0tXvc38U9m6z/t2RsVsnd1zM0g==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "requires": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "@types/react-test-renderer": { + "version": "16.9.5", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-16.9.5.tgz", + "integrity": "sha512-C4cN7C2uSSGOYelp2XfdtJb5TsCP+QiZ+0Bm4U3ZfUswN8oN9O/l86XO/OvBSFCmWY7w75fzsQvZ50eGkFN34A==", + "requires": { + "@types/react": "^16" + } + }, + "@types/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==", + "requires": { + "@types/react": "*" + } + }, + "@types/redux": { + "version": "3.6.31", + "resolved": "https://registry.npmjs.org/@types/redux/-/redux-3.6.31.tgz", + "integrity": "sha512-UEa68g5Q1EPG4Wsnxqhbl0luFVRyX5dbKF3MQstkoWawSNKLulS2WsZZbALsPUX4Ax6SY9faqEs6dPM47cBAcg==" + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + }, + "@types/semaphore": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/semaphore/-/semaphore-1.1.1.tgz", + "integrity": "sha512-jmFpMslMtBGOXY2s7x6O8vBebcj6zhkwl0Pd/viZApo1uZaPk733P8doPvaiBbCG+R7201OLOl4QP7l1mFyuyw==" + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "requires": { + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/socket.io-client": { + "version": "1.4.36", + "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.36.tgz", + "integrity": "sha512-ZJWjtFBeBy1kRSYpVbeGYTElf6BqPQUkXDlHHD4k/42byCN5Rh027f4yARHCink9sKAkbtGZXEAmR0ZCnc2/Ag==" + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "requires": { + "@types/node": "*" + } + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" + }, + "@types/stack-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz", + "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==" + }, + "@types/tailwindcss": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/tailwindcss/-/tailwindcss-3.1.0.tgz", + "integrity": "sha512-JxPzrm609hzvF4nmOI3StLjbBEP3WWQxDDJESqR1nh94h7gyyy3XSl0hn5RBMJ9mPudlLjtaXs5YEBtLw7CnPA==", + "requires": { + "tailwindcss": "*" + } + }, + "@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==" + }, + "@types/testing-library__dom": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@types/testing-library__dom/-/testing-library__dom-6.14.0.tgz", + "integrity": "sha512-sMl7OSv0AvMOqn1UJ6j1unPMIHRXen0Ita1ujnMX912rrOcawe4f7wu0Zt9GIQhBhJvH2BaibqFgQ3lP+Pj2hA==", + "requires": { + "pretty-format": "^24.3.0" + } + }, + "@types/testing-library__react": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/@types/testing-library__react/-/testing-library__react-9.1.3.tgz", + "integrity": "sha512-iCdNPKU3IsYwRK9JieSYAiX0+aYDXOGAmrC/3/M7AqqSDKnWWVv07X+Zk1uFSL7cMTUYzv4lQRfohucEocn5/w==", + "requires": { + "@types/react-dom": "*", + "@types/testing-library__dom": "*", + "pretty-format": "^25.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, + "@types/uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-3HO6rm0y+/cqvOyA8xcYLweF0TKXlAxmQASjbOi49Co51A1N4nR4bEwBgRoD9kNM+rqFGArjKr654SLp2CoGmQ==", + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "dev": true + }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" + }, + "@types/webpack": { + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", + "requires": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "@types/webpack-env": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.18.0.tgz", + "integrity": "sha512-56/MAlX5WMsPVbOg7tAxnYvNYMMWr/QJiIp6BxVSW3JJXUVzzOn64qW8TzQyMSqSUFM2+PVI4aUHcHOzIz/1tg==", + "dev": true + }, + "@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + } + } + }, + "@types/ws": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", + "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.35.1.tgz", + "integrity": "sha512-RBZZXZlI4XCY4Wzgy64vB+0slT9+yAPQRjj/HSaRwUot33xbDjF1oN9BLwOLTewoOI0jothIltZRe9uJCHf8gg==", + "requires": { + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/type-utils": "5.35.1", + "@typescript-eslint/utils": "5.35.1", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.35.1.tgz", + "integrity": "sha512-nF7JD9alMkhEx50QYDUdP8koeHtldnm7EfZkr68ikkc87ffFBIPkH3dqoWyOeQeIiJicB0uHzpMXKR6PP+1Jbg==", + "requires": { + "@typescript-eslint/utils": "5.35.1" + } + }, + "@typescript-eslint/parser": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.35.1.tgz", + "integrity": "sha512-XL2TBTSrh3yWAsMYpKseBYTVpvudNf69rPOWXWVBI08My2JVT5jR66eTt4IgQFHA/giiKJW5dUD4x/ZviCKyGg==", + "requires": { + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.35.1.tgz", + "integrity": "sha512-kCYRSAzIW9ByEIzmzGHE50NGAvAP3wFTaZevgWva7GpquDyFPFcmvVkFJGWJJktg/hLwmys/FZwqM9EKr2u24Q==", + "requires": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.35.1.tgz", + "integrity": "sha512-8xT8ljvo43Mp7BiTn1vxLXkjpw8wS4oAc00hMSB4L1/jIiYbjjnc3Qp2GAUOG/v8zsNCd1qwcqfCQ0BuishHkw==", + "requires": { + "@typescript-eslint/utils": "5.35.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.35.1.tgz", + "integrity": "sha512-FDaujtsH07VHzG0gQ6NDkVVhi1+rhq0qEvzHdJAQjysN+LHDCKDKCBRlZFFE0ec0jKxiv0hN63SNfExy0KrbQQ==" + }, + "@typescript-eslint/typescript-estree": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.35.1.tgz", + "integrity": "sha512-JUqE1+VRTGyoXlDWWjm6MdfpBYVq+hixytrv1oyjYIBEOZhBCwtpp5ZSvBt4wIA1MKWlnaC2UXl2XmYGC3BoQA==", + "requires": { + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/visitor-keys": "5.35.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.35.1.tgz", + "integrity": "sha512-v6F8JNXgeBWI4pzZn36hT2HXXzoBBBJuOYvoQiaQaEEjdi5STzux3Yj8v7ODIpx36i/5s8TdzuQ54TPc5AITQQ==", + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.35.1", + "@typescript-eslint/types": "5.35.1", + "@typescript-eslint/typescript-estree": "5.35.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.35.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.35.1.tgz", + "integrity": "sha512-cEB1DvBVo1bxbW/S5axbGPE6b7FIMAbo3w+AGq6zNDA7+NYJOIkKj/sInfTv4edxd4PxJSgdN4t6/pbvgA+n5g==", + "requires": { + "@typescript-eslint/types": "5.35.1", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@virtuoso.dev/react-urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/react-urx/-/react-urx-0.2.13.tgz", + "integrity": "sha512-MY0ugBDjFb5Xt8v2HY7MKcRGqw/3gTpMlLXId2EwQvYJoC8sP7nnXjAxcBtTB50KTZhO0SbzsFimaZ7pSdApwA==", + "requires": { + "@virtuoso.dev/urx": "^0.2.13" + } + }, + "@virtuoso.dev/urx": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@virtuoso.dev/urx/-/urx-0.2.13.tgz", + "integrity": "sha512-iirJNv92A1ZWxoOHHDYW/1KPoi83939o83iUBQHIim0i3tMeSKEh+bxhJdTHQ86Mr4uXx9xGUTq69cp52ZP8Xw==" + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + } + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + } + } + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + } + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "ace-builds": { + "version": "1.9.6", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.9.6.tgz", + "integrity": "sha512-M/Li4hPruMSbkkg35LgdbsIBq0WuwrV4ztP2pKaww47rC/MvDc1bOrYxwJrfgxdlzyLKrja5bn+9KwwuzqB2xQ==" + }, + "acorn": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", + "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + }, + "acorn-globals": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz", + "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==", + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "acorn-walk": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz", + "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==" + } + } + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + } + } + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha512-QbJ0NTQ/I9DI3uSJA4cbexiwQeRAfjPScqIbSjUDd9TOrcg6pTkdgziesOqxBMBzit8vFCTwrP27t13vFOORRA==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "airbnb-js-shims": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz", + "integrity": "sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "array.prototype.flatmap": "^1.2.1", + "es5-shim": "^4.5.13", + "es6-shim": "^0.35.5", + "function.prototype.name": "^1.1.0", + "globalthis": "^1.0.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0 || ^1.0.0", + "object.getownpropertydescriptors": "^2.0.3", + "object.values": "^1.1.0", + "promise.allsettled": "^1.0.0", + "promise.prototype.finally": "^3.1.0", + "string.prototype.matchall": "^4.0.0 || ^3.0.1", + "string.prototype.padend": "^3.0.0", + "string.prototype.padstart": "^3.0.0", + "symbol.prototype.description": "^1.0.0" + } + }, + "airbnb-prop-types": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", + "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", + "requires": { + "array.prototype.find": "^2.1.1", + "function.prototype.name": "^1.1.2", + "is-regex": "^1.1.0", + "object-is": "^1.1.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.13.1" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + } + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==" + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==" + }, + "anchorme": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/anchorme/-/anchorme-1.1.2.tgz", + "integrity": "sha512-/jQV4KaMWGSk+izs7KkqgoEbl+8dpePBbanE8OuwFD6Zrl8Vn1zi8w0ja5ZVRSrFnogkTag2YrNBWR6MRlwgbg==" + }, + "animated-scroll-to": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/animated-scroll-to/-/animated-scroll-to-2.3.0.tgz", + "integrity": "sha512-PT/5MSKCWQaK2kuOl2HT2KJMuJEvUS4/TgMhWy82c2EmF74/CIkvPBPKOvd8nMYP6Higo7xCn49/iSW9BccMoQ==" + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + } + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==" + }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-to-html": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz", + "integrity": "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==", + "dev": true, + "requires": { + "entities": "^2.0.0" + } + }, + "antd": { + "version": "4.22.8", + "resolved": "https://registry.npmjs.org/antd/-/antd-4.22.8.tgz", + "integrity": "sha512-mqHuCg9itZX+z6wk+mvRBcfz/U9iiIXS4LoNkyo8X/UBgdN8CoetFmrdvA1UQy1BuWa0/n62LiS1LatdvoTuHw==", + "requires": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons": "^4.7.0", + "@ant-design/react-slick": "~0.29.1", + "@babel/runtime": "^7.18.3", + "@ctrl/tinycolor": "^3.4.0", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "lodash": "^4.17.21", + "memoize-one": "^6.0.0", + "moment": "^2.29.2", + "rc-cascader": "~3.6.0", + "rc-checkbox": "~2.3.0", + "rc-collapse": "~3.3.0", + "rc-dialog": "~8.9.0", + "rc-drawer": "~5.1.0", + "rc-dropdown": "~4.0.0", + "rc-field-form": "~1.27.0", + "rc-image": "~5.7.0", + "rc-input": "~0.0.1-alpha.5", + "rc-input-number": "~7.3.5", + "rc-mentions": "~1.9.1", + "rc-menu": "~9.6.3", + "rc-motion": "^2.6.1", + "rc-notification": "~4.6.0", + "rc-pagination": "~3.1.17", + "rc-picker": "~2.6.10", + "rc-progress": "~3.3.2", + "rc-rate": "~2.9.0", + "rc-resize-observer": "^1.2.0", + "rc-segmented": "~2.1.0", + "rc-select": "~14.1.1", + "rc-slider": "~10.0.0", + "rc-steps": "~4.1.0", + "rc-switch": "~3.2.0", + "rc-table": "~7.25.3", + "rc-tabs": "~11.16.0", + "rc-textarea": "~0.3.0", + "rc-tooltip": "~5.2.0", + "rc-tree": "~5.6.5", + "rc-tree-select": "~5.4.0", + "rc-trigger": "^5.2.10", + "rc-upload": "~4.3.0", + "rc-util": "^5.22.5", + "scroll-into-view-if-needed": "^2.2.25" + } + }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha512-jlpIfsOoNoafl92Sz//64uQHGSyMrD2vYG5d8o2a4qGvyNCvXur7bzIsWtAC/6flI2RYAp3kv8rsfBtaLm7w0g==", + "dev": true + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", + "requires": { + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + } + }, + "arity-n": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arity-n/-/arity-n-1.0.4.tgz", + "integrity": "sha512-fExL2kFDC1Q2DUOx3whE/9KoN66IzkY4b4zUHUBFM1ojEYjZZYDcUW3bek/ufGionX9giIKDC5redH2IlGqcQQ==" + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==", + "optional": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha512-H3LU5RLiSsGXPhN+Nipar0iR0IofH+8r89G2y1tBKxQ/agagKyAjhkAFDRBfodP2caPrNKHpAWNIM/c9yeL7uA==" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", + "dev": true, + "optional": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==", + "optional": true + }, + "array.prototype.filter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.1.tgz", + "integrity": "sha512-Dk3Ty7N42Odk7PjU/Ci3zT4pLj20YvuVnneG/58ICM6bt4Ij5kZaJTVQ9TSaWaIECX2sFyz4KItkVZqHNnciqw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "array.prototype.find": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.2.0.tgz", + "integrity": "sha512-sn40qmUiLYAcRb/1HsIQjTTZ1kCy8II8VtZJpMn2Aoen9twULhbWXisfh3HimGqMlHGUul0/TfKCnXg42LuPpQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz", + "integrity": "sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", + "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "array.prototype.reduce": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz", + "integrity": "sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arraybuffer.slice": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", + "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "requires": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" + }, + "ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "dev": true, + "requires": { + "tslib": "^2.0.1" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "optional": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autolinker": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-3.16.0.tgz", + "integrity": "sha512-KY8yhlwvuQpA7exkkvHsmk0chdrtS0ZRO7XoPfs7w8N3kpiGPjYNDrQ0lIMx2GrKFZzGK/QSEd2Sx5SYtSNBKg==", + "requires": { + "tslib": "^2.3.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "await-lock": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", + "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "axe-core": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz", + "integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==" + }, + "axobject-query": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha512-wau+BDtQfuSBGQ9PzzFL3REvR9Sxnd4LKwtcHAiPjhugA7K/80vpHXafj+O5bAqJOuSefjOx5ZJnNSR2J1Qw6Q==", + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "optional": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "optional": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==", + "optional": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha512-mk8fAWcRUOxY7btlLtitj3A45jOwSAxH4tOFOoEGbVsl6cL6pPMWUy7dwZ/canfj3QEdP6FHSnf/l1c6/WkzVg==", + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==", + "optional": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "optional": true, + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "optional": true + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "optional": true, + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "optional": true + } + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "optional": true + } + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "optional": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==", + "optional": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "optional": true + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==" + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==" + } + } + }, + "babel-extract-comments": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/babel-extract-comments/-/babel-extract-comments-1.0.0.tgz", + "integrity": "sha512-qWWzi4TlddohA91bFwgt6zO/J0X+io7Qp184Fw0m2JYRSTZnJbFR8+07KmzudHCZgOiKRCrjhylwv9Xd8gfhVQ==", + "requires": { + "babylon": "^6.18.0" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA==" + } + } + }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha512-TYX2QQATKA6Wssp6j7jqlw4QLmABDN1olRdEHndYvBXdaXM5dcx6j5rN0+nd+aVL+Th40fAEYvvw/Xxd/LETuQ==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha512-gCtfYORSG1fUMX4kKraymq607FWgMWg+j42IFPc18kFQEsmtaibP4UrqsXt8FlEJle25HUd4tsoDR7H2wDhe9Q==", + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha512-02I9jDjnVEuGy2BR3LRm9nPRb/+Ja0pvZVLr1eI5TYAA/dB0Xoc+WBo50+aDfhGDLhlBY1+QURjn9uvcFd8gzg==", + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "esutils": "^2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha512-RL8n2NiEj+kKztlrVJM9JT1cXzzAdvWFh76xh/H1I4nKwunzE4INBXn8ieCZ+wh4zWszZk7NBS1s/8HR5jDkzQ==", + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha512-bHkmjcC9lM1kmZcVpA5t2om2nzT/xiZpo6TJq7UlZ3wqKfzia4veeXbIhKvJXAMzhhEBd3cR1IElL5AenWEUpA==", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha512-qe5csbhbvq6ccry9G7tkXbzNtcDiH4r51rrPUbwwoTzZ18AqxWYRZT6AOmxrpxKnQBW0pYlBI/8vh73Z//78nQ==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha512-SFbWewr0/0U4AiRzsHqwsbOQeLXVa9T1ELdqEa2efcQB5KopTnunAqoj07TuHlN2lfTQNPGO/rJR4FMln5fVcA==", + "requires": { + "babel-helper-bindify-decorators": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q==", + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha512-zAYl3tqerLItvG5cKYw7f1SpvIxS9zi7ohyGHaI9cgDUjAT6YcY9jIEH5CstetP5wHIVSceXwNS7Z5BpJg+rOw==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha512-Op9IhEaxhbRT8MDXx2iNuMgciu2V8lDvYCNQbDGjdBNCjaMvyLf4wl4A3b8IgndCyQF8TwfgsQ8T3VD8aX1/pA==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha512-VlPiWmqmGJp0x0oK27Out1D+71nVVCTSdlbhIVoaBAj2lUgrNjBCRR9+llO4lTSb2O4r7PJg+RobRkhBrf6ofg==", + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha512-RYqaPD0mQyQIFRu7Ho5wE2yvA/5jxqCIj/Lv4BXNq23mHYu/vxikOy2JueLiBxQknwapwrJeNCesvY0ZcfnlHg==", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha512-sLI+u7sXJh6+ToqDr57Bv973kCepItDhMou0xCP2YPVmR1jkHSCY+p1no8xErbV1Siz5QE8qKT1WIwybSWlqjw==", + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha512-n7pFrqQm44TCYvrCDb0MqabAF+JUBq+ijBvNMUxpkLjJaAu32faIexewMumrH5KLLJ1HDyT0PTEqRyAe/GwwuQ==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "babel-loader": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", + "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^2.0.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-add-react-displayname": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/babel-plugin-add-react-displayname/-/babel-plugin-add-react-displayname-0.0.5.tgz", + "integrity": "sha512-LY3+Y0XVDYcShHHorshrDbt4KFWL4bSeniCtl4SYZbask+Syngk1uMPCeN9+nSiZo6zX5s0RTq/J9Pnaaf/KHw==", + "dev": true + }, + "babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha512-B1M5KBP29248dViEo1owyY32lk1ZSH2DaNNrXLGt8lyjjHm7pBqAdQ7VKUPR6EEDO323+OvT3MQXbCin8ooWdA==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, + "babel-plugin-import": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/babel-plugin-import/-/babel-plugin-import-1.13.5.tgz", + "integrity": "sha512-IkqnoV+ov1hdJVofly9pXRJmeDm9EtROfrc5i6eII0Hix2xMs5FEm8FG3ExMvazbnZBbgHIt6qdO8And6lCloQ==", + "requires": { + "@babel/helper-module-imports": "^7.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + } + } + }, + "babel-plugin-named-asset-import": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", + "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==" + }, + "babel-plugin-named-exports-order": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-named-exports-order/-/babel-plugin-named-exports-order-0.0.2.tgz", + "integrity": "sha512-OgOYHOLoRK+/mvXU9imKHlG6GkPLYrUCvFXG/CM93R/aNNO8pOOF4aS+S8CCHMDQoNSeiOYEZb/G6RwL95Jktw==", + "dev": true + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", + "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==", + "requires": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.2", + "semver": "^6.1.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.2", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz", + "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.2" + } + }, + "babel-plugin-react-docgen": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz", + "integrity": "sha512-UQ0NmGHj/HAqi5Bew8WvNfCk8wSsmdgNd8ZdMjBCICtyCJCq9LiqgqvjCYe570/Wg7AQArSq1VQ60Dd/CHN7mQ==", + "dev": true, + "requires": { + "ast-types": "^0.14.2", + "lodash": "^4.17.15", + "react-docgen": "^5.0.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha512-4Zp4unmHgw30A1eWI5EpACji2qMocisdXhAftfhXoSV9j0Tvj6nRFE3tOmRY912E0FMRm/L5xWE7MGVT2FoLnw==" + }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha512-EbciFN5Jb9iqU9bqaLmmFLx2G8pAUsvpWJ6OzOWBNrSY9qTohXj+7YfZx6Ug1Qqh7tCb1EA7Jvn9bMC1HBiucg==" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha512-EEuBcXz/wZ81Jaac0LnMHtD4Mfz9XWn2oH2Xj+CHwz2SZWUqqdtR2BgWPSdTGMmxN/5KLSh4PImt9+9ZedDarA==" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha512-chI3Rt9T1AbrQD1s+vxw3KcwC9yHtF621/MacuItITfZX344uhQoANjpoSJZleAmW2tjlolqB/f+h7jIqXa7pA==" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha512-AWj19x2aDm8qFQ5O2JcD6pwJDW1YdcnO+1b81t7gxrGjz5VHiUqeYWAR4h7zueWMalRelrQDXprv2FrY1dbpbw==" + }, + "babel-plugin-syntax-do-expressions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", + "integrity": "sha512-HD/5qJB9oSXzl0caxM+aRD7ENICXqcc3Up/8toDQk7zNIDE7TzsqtxC5f4t9Rwhu2Ya8l9l4j6b3vOsy+a6qxg==" + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha512-MioUE+LfjCEz65Wf7Z/Rm4XCP5k2c+TbMd2Z2JKc7U9uwjBhAfNPE48KC4GTGKhppMeYVepwDBNO/nGY6NYHBA==" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha512-Z/flU+T9ta0aIEKl1tGEmN/pZiI1uXmCiGFRegKacQfEJzp7iNsKloZmyJlQr+75FCJtiFfGIK03SiCvCt9cPQ==" + }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha512-Eo0rcRaIDMld/W6mVhePiudIuLW+Cr/8eveW3mBREfZORScZgx4rh6BAPyvzdEc/JZvQ+LkC80t0VGFs6FX+lg==" + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha512-HbTDIoG1A1op7Tl/wIFQPULIBA61tsJ8Ntq2FAhLwuijrzosM/92kAfgU1Q3Kc7DH/cprJg5vDfuTY4QUL4rDA==" + }, + "babel-plugin-syntax-function-bind": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", + "integrity": "sha512-m8yMoh9LIiNyeLdQs5I9G+3YXo4nqVsKQkk7YplrG4qAFbNi9hkZlow8HDHxhH9QOVFPHmy8+03NzRCdyChIKw==" + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==" + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha512-C4Aq+GaAj83pRQ0EFgTvw5YO6T3Qz2KGrNRwIj9mSoNHVvdZY4KO2uA6HNtNXCw993iSZnckY1aLW8nOi8i4+w==" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha512-Gx9CH3Q/3GKbhs07Bszw5fPTlU+ygrOGfAhEt7W2JICwufpC4SuO0mG0+4NykPBSYPMJhqvVlDBU17qB1D+hMQ==" + }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha512-uT7eovUxtXe8Q2ufcjRuJIOL0hg6VAUJhiWJBLxH/evYAw+aqoJLcYTR8hqx13iOx/FfbCMHgBmXWZjukbkyPg==", + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-generators": "^6.5.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha512-7BgYJujNCg0Ti3x0c/DL3tStvnKS6ktIYOmo9wginv/dfZOrbSZ+qG4IRRHMBOzZ5Awb1skTiAsQXg/+IWkZYw==", + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha512-RvYukT1Nh7njz8P8326ztpQUGCKwmjgu6aRIx1lkvylWITYcskg29vy1Kp8WXIq7FvhXsz0Crf2kS94bjB690A==", + "requires": { + "babel-plugin-syntax-class-constructor-call": "^6.18.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha512-n4jtBA3OYBdvG5PRMKsMXJXHfLYw/ZOmtxCLOOwz6Ro5XlrColkStLnz1AS1L2yfPA9BKJ1ZNlmVCLjAL9DSIg==", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-plugin-syntax-class-properties": "^6.8.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha512-skQ2CImwDkCHu0mkWvCOlBCpBIHW4/49IZWVwV4A/EnWjL9bB6UBvLyMNe3Td5XDStSZNhe69j4bfEW8dvUbew==", + "requires": { + "babel-helper-explode-class": "^6.24.1", + "babel-plugin-syntax-decorators": "^6.13.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-do-expressions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", + "integrity": "sha512-yQwYqYg+Tnj1InA8W1rsItsZVhkv1Euc4KVua9ledtPz5PDWYz7LVyy6rDBpVYUWFZj5k6GUm3YZpCbIm8Tqew==", + "requires": { + "babel-plugin-syntax-do-expressions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha512-PCqwwzODXW7JMrzu+yZIaYbPQSKjDTAsNNlK2l5Gg9g4rz2VzLnZsStvp/3c46GfXpwkyufb3NCyG9+50FF1Vg==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha512-2+ujAT2UMBzYFm7tidUsYh+ZoIutxJ3pN9IYrF1/H6dCKtECfhmB8UkHVpyxDwkj0CYbQG35ykoz925TUnBc3A==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha512-YiN6sFAQ5lML8JjCmr7uerS5Yc/EMbgg9G8ZNmk2E3nYX4ckHR01wrkeeMijEf5WHNK5TW0Sl0Uu3pv3EdOJWw==", + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha512-5Dy7ZbRinGrNtmWpquZKZ3EGY8sDgIVB4CU8Om8q8tnMLrD/m94cKglVcHps0BCTdZ0TJeeAWOq2TK9MIY6cag==", + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha512-C/uAv4ktFP/Hmh01gMTvYvICrKze0XVX9f2PdIXuriCSvUmV9j+u+BB9f5fJK3+878yMK6dkdcq+Ymr9mrcLzw==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha512-aNv/GDAW0j/f4Uy1OEPZn1mqD+Nfy9viFGBfQ5bZyT35YqOiqx7/tXdyfZkJ1sC21NyEsBdfDY6PYmLHF4r5iA==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha512-ossocTuPOssfxO2h+Z3/Ea1Vo1wWx31Uqy9vIiJusOP4TbF7tPs9U0sJ9pX9OJPf4lXRGj5+6Gkl/HHKiAP5ug==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha512-DLuRwoygCoXx+YfxHLkVx5/NpeSbVwfoTeBykpJK7JhYWlL/O8hgAK/reforUnZDlxasOrVPPJVI/guE3dCwkw==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha512-iFp5KIcorf11iBqu/y/a7DK3MN5di3pNCzto61FqCNnUX4qeBwcV1SLqe10oXNnCaxBUImX3SckX2/o1nsrTcg==", + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha512-tjFl0cwMPpDYyoqYA9li1/7mGFit39XiNX5DKC/uCNjBctMxyL1/PT/l4rSlbvBG1pOKI88STRdUsWXB3/Q9hQ==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha512-LnIIdGWIKdw7zwckqx+eGjcS8/cl8D74A3BpJbGjKTFFNJSMrjN4bIh22HY1AlkUbeLG6X6OZj56BDvWD+OeFA==", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha512-ONFIPsq8y4bls5PPsAWYXH/21Hqv64TBxdje0FvU3MhIV6QM2j5YS7KvAzg/nTIVLot2D2fmFQrFWCbgHlFEjg==", + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha512-LpVbiT9CLsuAIp3IG0tfbVo81QIhn6pE8xBJ7XSeCtFlMltuar5VuBV6y6Q45tpui9QWcy5i0vLQfCfrnF7Kiw==", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha512-8G5hpZMecb53vpD3mjs64NhI1au24TAmokQ4B+TBFBjN9cVoGoOvotdrMMRmHvVZUEvqGUPWL514woru1ChZMA==", + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha512-8HxlW+BB5HqniD+nLkQ4xSAVq3bR/pcYW9IigY+2y0dI+Y7INFeTbfAQr+63T3E4UDsZGjyb+l9txUnABWxlOQ==", + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha512-mDdocSfUVm1/7Jw/FIRNw9vPrBQNePy6wZJlR8HAUBLybNp1w/6lr6zZ2pjMShee65t/ybR5pT8ulkLzD1xwiw==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha512-3Ghhi26r4l3d0Js933E5+IhHwk0A1yiutj9gwvzmFbVV0sPMYk2lekhOufHBswX7NCoSeF4Xrl3sCIuSIa+zOg==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha512-CYP359ADryTo3pCsH0oxRo/0yn6UsEZLqYohHmvLQdfS9xkf+MbCzE3/Kolw9OYIY4ZMilH25z/5CbQbwDD+lQ==", + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha512-x8b9W0ngnKzDMHimVtTfn5ryimars1ByTqsfBDwAqLibmuuQY6pgBQi5z1ErIsUOWBdw1bW9FSz5RZUojM4apg==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha512-fz6J2Sf4gYN6gWgRZaoFXmq93X+Li/8vf+fb0sGDVtdeWvxC9y5/bTD7bvfWMEq6zetGEHpWjtzRGSugt5kNqw==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha512-v61Dbbihf5XxnYjtBN04B/JBvsScY37R1cZT5r9permN1cp+b70DY3Ib3fIkgn1DI9U3tGgBJZVD8p/mE/4JbQ==", + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha512-tJ9+S4oKjxY8IZ9jmjnp/mtytu1u3iyIQAfmI51IKWH6bFf7XR1ybtaO6j7INhZKXOTYADk7V5qxaqLkmNxiZQ==", + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha512-x+Y3yA24uF68m5GA+tBjbGYo64xXVJpbToBaWCoSNSc1hdk6dfctaRWrNFTVJZIIhL5GxW8zwjoixbnifnK59g==" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha512-jlQ9gYLfk2p3V5Ag5fYhA7fv7OHzd1KUH0PRP46xc3TgwjwgROIW572AfYg/X9kaNq/LJnu6oJcFRXlIrGoTRw==", + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha512-LzXDmbMkklvNhprr20//RStKVcT8Cu+SQtX18eMHLhjHf2yFzwtQ0S2f0jQ+89rokoNdmwoSqYzAhq86FxlLSQ==", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha512-mtzELzINaYqdVglyZrDDVwkcFRuE7s6QUFWXxwffKAHB/NkfbJ2NJSytugB43ytIC8UVt30Ereyx+7gNyTkDLg==", + "requires": { + "babel-plugin-syntax-export-extensions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha512-TxIM0ZWNw9oYsoTthL3lvAK3+eTujzktoXJg4ubGvICGbVuXVYv5hHv0XXpz8fbqlJaGYY4q5SVzaSmsg3t4Fg==", + "requires": { + "babel-plugin-syntax-flow": "^6.18.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-function-bind": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", + "integrity": "sha512-9Ec4KYf1GurT39mlUjDSlN7HWSlB3u3mWRMogQbb+Y88lO0ZM3rJ0ADhPnQwWK9TbO6e/4E+Et1rrfGY9mFimA==", + "requires": { + "babel-plugin-syntax-function-bind": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha512-ocgA9VJvyxwt+qJB0ncxV8kb/CjfTcECUY4tQ5VT7nP6Aohzobm8CDFaQ5FHdvZQzLmf0sgDxB8iRXZXxwZcyA==", + "requires": { + "babel-plugin-syntax-object-rest-spread": "^6.8.0", + "babel-runtime": "^6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha512-QLYkLiZeeED2PKd4LuXGg5y9fCgPB5ohF8olWUuETE2ryHNRqqnXlEVP7RPuef89+HTfd3syptMGVHeoAu0Wig==", + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha512-s+q/Y2u2OgDPHRuod3t6zyLoV8pUHc64i/O7ZNgIOEdYTq+ChPeybcKBi/xk9VI60VriILzFPW+dUxAEbTxh2w==", + "requires": { + "babel-helper-builder-react-jsx": "^6.24.1", + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha512-Y3ZHP1nunv0U1+ysTNwLK39pabHj6cPVsfN4TRC7BDBfbgbyF4RifP5kd6LnbuMV9wcfedQMe7hn1fyKc7IzTQ==", + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha512-pcDNDsZ9q/6LJmujQ/OhjeoIlp5Nl546HJ2yiFIJK3mYpgNXhI5/S9mXfVxu5yqWAi7HdI7e/q6a9xtzwL69Vw==", + "requires": { + "babel-plugin-syntax-jsx": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-react-remove-prop-types": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", + "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha512-LS+dBkUGlNR15/5WHKe/8Neawx663qttS6AGqoOUhICc9d1KciBvtrQSuc0PI+CxQ2Q/S1aKuJ+u64GtLdcEZg==", + "requires": { + "regenerator-transform": "^0.10.0" + }, + "dependencies": { + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + } + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha512-j3KtSpjyLSJxNoCDrhwiJad8kw0gJ9REGj8/CqL0HeRyLnvUNYV9zcqluL6QJSXh3nfsLEmSLvwRfGzrgR96Pw==", + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha512-F2rZGQnAdaHWQ8YAoeRbukc7HS9QgdgeyJ0rQDd485v9opwuPvjpPFcOOT/WmkKTdgy9ESgSPXDcTNpzrGr6iQ==", + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha512-02YopEIhAgiBHWeoTiA8aitHDt8z6w+rQqNuIftlM+ZtvSl/brTouaU7DW6GO/cHtvxJvS4Hwv2ibKdxIRi24w==" + } + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + }, + "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "babel-preset-es2017": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz", + "integrity": "sha512-3iPqwP/tBkRATDg9qKkuycGEi1FZCF9pYoa2orhBynoQEPIelORSbk5VqbBI6+UzAt0CGG2gOfj46fmUmuz32g==", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.24.1" + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha512-PQZFJXnM3d80Vq4O67OE6EMVKIw2Vmzy8UXovqulNogCtblWU8rzP7Sm5YgHiCg4uejUxzCkHfNXQ4Z6GI+Dhw==", + "requires": { + "babel-plugin-transform-flow-strip-types": "^6.22.0" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha512-phQe3bElbgF887UM0Dhz55d22ob8czTL1kbhZFwpCE6+R/X9kHktfwmx9JZb+bBSVRGphP5tZ9oWhVhlgjrX3Q==", + "requires": { + "babel-plugin-syntax-jsx": "^6.3.13", + "babel-plugin-transform-react-display-name": "^6.23.0", + "babel-plugin-transform-react-jsx": "^6.24.1", + "babel-plugin-transform-react-jsx-self": "^6.22.0", + "babel-plugin-transform-react-jsx-source": "^6.22.0", + "babel-preset-flow": "^6.23.0" + } + }, + "babel-preset-react-app": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.1.2.tgz", + "integrity": "sha512-k58RtQOKH21NyKtzptoAvtAODuAJJs3ZhqBMl456/GnXEQ/0La92pNmwgWoMn5pBTrsvk3YYXdY7zpY4e3UIxA==", + "requires": { + "@babel/core": "7.9.0", + "@babel/plugin-proposal-class-properties": "7.8.3", + "@babel/plugin-proposal-decorators": "7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.8.3", + "@babel/plugin-proposal-numeric-separator": "7.8.3", + "@babel/plugin-proposal-optional-chaining": "7.9.0", + "@babel/plugin-transform-flow-strip-types": "7.9.0", + "@babel/plugin-transform-react-display-name": "7.8.3", + "@babel/plugin-transform-runtime": "7.9.0", + "@babel/preset-env": "7.9.0", + "@babel/preset-react": "7.9.1", + "@babel/preset-typescript": "7.9.0", + "@babel/runtime": "7.9.0", + "babel-plugin-macros": "2.8.0", + "babel-plugin-transform-react-remove-prop-types": "0.4.24" + }, + "dependencies": { + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", + "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", + "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", + "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/preset-env": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.0.tgz", + "integrity": "sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==", + "requires": { + "@babel/compat-data": "^7.9.0", + "@babel/helper-compilation-targets": "^7.8.7", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.9.0", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.9.0", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-umd": "^7.9.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.7", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.7", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.9.0", + "browserslist": "^4.9.1", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-react": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.1.tgz", + "integrity": "sha512-aJBYF23MPj0RNdp/4bHnAP0NVqqZRr9kl0NAOP4nJCex6OYVio59+dnQzsAWFuogdLyeaKA1hmfUIVZkY5J+TQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-react-display-name": "^7.8.3", + "@babel/plugin-transform-react-jsx": "^7.9.1", + "@babel/plugin-transform-react-jsx-development": "^7.9.0", + "@babel/plugin-transform-react-jsx-self": "^7.9.0", + "@babel/plugin-transform-react-jsx-source": "^7.9.0" + } + }, + "@babel/runtime": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.0.tgz", + "integrity": "sha512-cTIudHnzuWLS56ik4DnRnqqNf8MkdUzV4iFFI1h7Jo9xvrpQROYaAnaSd2mHLQAzzZAPfATynX5ord6YlNYNMA==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "babel-preset-stage-0": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.24.1.tgz", + "integrity": "sha512-MJD+xBbpsApbKlzAX0sOBF+VeFaUmv5s8FSOO7SSZpes1QgphCjq/UIGRFWSmQ/0i5bqQjLGCTXGGXqcLQ9JDA==", + "requires": { + "babel-plugin-transform-do-expressions": "^6.22.0", + "babel-plugin-transform-function-bind": "^6.22.0", + "babel-preset-stage-1": "^6.24.1" + } + }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha512-rn+UOcd7BHDniq1SVxv2/AVVSVI1NK+hfS0I/iR6m6KbOi/aeBRcqBilqO73pd9VUpRXF2HFtlDuC9F2BEQqmg==", + "requires": { + "babel-plugin-transform-class-constructor-call": "^6.24.1", + "babel-plugin-transform-export-extensions": "^6.22.0", + "babel-preset-stage-2": "^6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha512-9F+nquz+37PrlTSBdpeQBKnQfAMNBnryXw+m4qBh35FNbJPfzZz+sjN2G5Uf1CRedU9PH7fJkTbYijxmkLX8Og==", + "requires": { + "babel-plugin-syntax-dynamic-import": "^6.18.0", + "babel-plugin-transform-class-properties": "^6.24.1", + "babel-plugin-transform-decorators": "^6.24.1", + "babel-preset-stage-3": "^6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha512-eCbEOF8uN0KypFXJmZXn2sTk7bPV9uM5xov7G/7BM08TbQEObsVs0cEWfy6NQySlfk7JBi/t+XJP1JkruYfthA==", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-generator-functions": "^6.24.1", + "babel-plugin-transform-async-to-generator": "^6.24.1", + "babel-plugin-transform-exponentiation-operator": "^6.24.1", + "babel-plugin-transform-object-rest-spread": "^6.22.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha512-veliHlHX06wjaeY8xNITbveXSiI+ASFnOqvne/LaIJIqOWi2Ogmj91KOugEz/hoh/fwMhXNBJPCv8Xaz5CyM4A==", + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + }, + "dependencies": { + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==" + } + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "backo2": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", + "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==" + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "base64-arraybuffer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", + "integrity": "sha512-a1eIFi4R9ySrbiMuyTGx5e92uRH5tQY6kArNcFaKBUleIoLjdjBg7Zxm3Mqm3Kmkf27HLR/1fnxX9q8GQ7Iavg==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "better-opn": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", + "integrity": "sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==", + "dev": true, + "requires": { + "open": "^7.0.3" + } + }, + "bfj": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", + "integrity": "sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==", + "requires": { + "bluebird": "^3.5.5", + "check-types": "^11.1.1", + "hoopy": "^0.1.4", + "tryer": "^1.0.1" + } + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "dev": true, + "optional": true + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "blob": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "bonjour-service": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.13.tgz", + "integrity": "sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==", + "requires": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "bowser": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-0.7.3.tgz", + "integrity": "sha512-N/toHA87JcmAHPqU8Qt7YnhFK6W2WUpdq5M1k/JqLdTqtts7sHEMZhFjFWTvvR2poKF7Qki0qknhIPIr5I7TIQ==" + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "bplist-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.1.1.tgz", + "integrity": "sha512-2AEM0FXy8ZxVLBuqX0hqt1gDwcnz2zygEkQ6zaD5Wko/sB9paUNwlpawrFtKeHUAQUOzjVy9AO4oeonqIHKA9Q==", + "dev": true, + "optional": true, + "requires": { + "big-integer": "^1.6.7" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==" + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "c8": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", + "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==" + } + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==", + "dev": true, + "optional": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==", + "dev": true, + "optional": true + } + } + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001384", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001384.tgz", + "integrity": "sha512-BBWt57kqWbc0GYZXb47wTXpmAgqr5LSibPzNjk/AWMdmJMQhLqOl3c/Kd4OAU/tu4NLfYkMx8Tlq3RVBkOBolQ==" + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "requires": { + "rsvp": "^4.8.4" + } + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + }, + "ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true + }, + "check-types": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz", + "integrity": "sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==" + }, + "cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "requires": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "dependencies": { + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==" + } + } + }, + "cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "requires": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "dependencies": { + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==" + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==" + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "classnames": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", + "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + }, + "clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cli-table3": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz", + "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha512-we+NuQo2DHhSl+DP6jlUiAhyAjBQrYnpOk15rN6c6JSPScjiCLh8IbSU+VTcph6YS3o7mASE8a0+gbZ7ChLpgg==", + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + } + }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "combokeys": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/combokeys/-/combokeys-3.0.1.tgz", + "integrity": "sha512-5nAfaLZ3oO3kA+/xdoL7t197UJTz2WWidyH3BBeU6hqHtvyFERICd0y3DQFrQkJFTKBrtUDck/xCLLoFpnjaCw==" + }, + "comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "component-bind": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", + "integrity": "sha512-WZveuKPeKAG9qY+FkYDeADzdHyTYdIboXS59ixDeRJL5ZhxpqUnxSOwop4FQjMsiYm3/Or8cegVbpAHNA7pHxw==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "component-inherit": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", + "integrity": "sha512-w+LhYREhatpVqTESyGFg3NlP6Iu0kEKUHETY9GoZP/pQyW4mHFZuFWRUCIqVPZ36ueVLtoOEZaAqbCF2RDndaA==" + }, + "compose-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/compose-function/-/compose-function-3.0.3.tgz", + "integrity": "sha512-xzhzTJ5eC+gmIzvZq+C3kCJHsp9os6tJkrigDRZclyGtOKINbZtE8n1Tzmeh32jW+BUDPbvZpibwvJHBLGMVwg==", + "requires": { + "arity-n": "^1.0.4" + } + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==" + }, + "computed-style": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/computed-style/-/computed-style-0.1.4.tgz", + "integrity": "sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concurrently": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.3.0.tgz", + "integrity": "sha512-IiDwm+8DOcFEInca494A8V402tNTQlJaYq78RF2rijOrKEk/AOHTxhN4U1cp7GYKYX5Q6Ymh1dLTBlzIMN0ikA==", + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "config": { + "version": "1.31.0", + "resolved": "https://registry.npmjs.org/config/-/config-1.31.0.tgz", + "integrity": "sha512-Ep/l9Rd1J9IPueztJfpbOqVzuKHQh4ZODMNt9xqTYdBBNRXbV4oTu34kCkkfdRVcDq0ohtpaeXGgb+c0LQxFRA==", + "requires": { + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==" + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "consolidated-events": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/consolidated-events/-/consolidated-events-2.0.2.tgz", + "integrity": "sha512-2/uRVMdRypf5z/TW/ncD/66l75P5hH2vM/GR8Jf8HLc2xnfJtmina6F6du8+v4Z2vTrMo7jC+W1tmEEuuELgkQ==" + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "requires": { + "is-what": "^3.14.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==" + }, + "copy-to-clipboard": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz", + "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "core-js-compat": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz", + "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==", + "requires": { + "browserslist": "^4.21.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "core-js-pure": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.0.tgz", + "integrity": "sha512-IeHpLwk3uoci37yoI2Laty59+YqH9x5uR65/yiA0ARAJrTrN4YU0rmauLWfvqOuk77SlNJXj2rM6oT/dBD87+A==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cosmiconfig-typescript-loader": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.9.tgz", + "integrity": "sha512-tRuMRhxN4m1Y8hP9SNYfz7jRwt8lZdWxdjg/ohg5esKmsndJIn4yT96oJVcf5x0eA11taXl+sIp+ielu529k6g==", + "requires": { + "cosmiconfig": "^7", + "ts-node": "^10.7.0" + } + }, + "cp-file": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", + "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "nested-error-stacks": "^2.0.0", + "p-event": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + } + } + }, + "cpy": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/cpy/-/cpy-8.1.2.tgz", + "integrity": "sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==", + "dev": true, + "requires": { + "arrify": "^2.0.1", + "cp-file": "^7.0.0", + "globby": "^9.2.0", + "has-glob": "^1.0.0", + "junk": "^3.1.0", + "nested-error-stacks": "^2.1.0", + "p-all": "^2.1.0", + "p-filter": "^2.1.0", + "p-map": "^3.0.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true + } + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "craco-alias": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/craco-alias/-/craco-alias-2.3.1.tgz", + "integrity": "sha512-i+N5JGpH61QChhfMtZsuy/5btncn9EczOq1XjaPPzBbzmQISAh0JtQhwMzIqefQfSNmRNgh4vePRJwfzroyaSA==", + "dev": true + }, + "craco-less": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/craco-less/-/craco-less-2.0.0.tgz", + "integrity": "sha512-980mQaZVrC4ZsvOwvud6/AgvW7fLY3mW5m5+gR4sw4krxszgHb+qoRyOjqsYPD0F4oUmQoSiZSrlYY/bFGD9kQ==", + "requires": { + "less": "^4.1.1", + "less-loader": "^7.3.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==" + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-minimizer-webpack-plugin": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", + "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", + "requires": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "postcss": "^8.3.5", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "css-declaration-sorter": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz", + "integrity": "sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==" + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "cssnano": { + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.13.tgz", + "integrity": "sha512-S2SL2ekdEz6w6a2epXn4CmMKU4K3KpcyXLKfAYc9UQQqJRkD/2eLUG0vJ3Db/9OvO5GuAdgXw3pFbR6abqghDQ==", + "requires": { + "cssnano-preset-default": "^5.2.12", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.12.tgz", + "integrity": "sha512-OyCBTZi+PXgylz9HAA5kHyoYhfGcYdwFmyaJzWnzxuGRtnMw/kR6ilW9XzlzlRAtB6PLT/r+prYgkef7hngFew==", + "requires": { + "css-declaration-sorter": "^6.3.0", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.0", + "postcss-convert-values": "^5.1.2", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.6", + "postcss-merge-rules": "^5.1.2", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.3", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.0", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.0", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-colormin": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", + "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz", + "integrity": "sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==", + "requires": { + "browserslist": "^4.20.3", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==" + }, + "postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==" + }, + "postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==" + }, + "postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==" + }, + "postcss-merge-longhand": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.6.tgz", + "integrity": "sha512-6C/UGF/3T5OE2CEbOuX7iNO63dnvqhGZeUnKkDeifebY0XqkkvrctYSZurpNE902LDf2yKwwPFgotnfSoPhQiw==", + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.0" + } + }, + "postcss-merge-rules": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz", + "integrity": "sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==", + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz", + "integrity": "sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==", + "requires": { + "browserslist": "^4.16.6", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==" + }, + "postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz", + "integrity": "sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==", + "requires": { + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "requires": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-reduce-initial": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz", + "integrity": "sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==", + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + } + }, + "postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stylehacks": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", + "integrity": "sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==", + "requires": { + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + } + } + } + }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "css-vendor": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", + "integrity": "sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==", + "requires": { + "@babel/runtime": "^7.8.3", + "is-in-browser": "^1.0.2" + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==" + }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==" + }, + "cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw==" + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw==" + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==" + }, + "cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==" + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "cssstyle": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", + "requires": { + "cssom": "0.3.x" + } + }, + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", + "dev": true, + "optional": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "custom-protocol-check": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/custom-protocol-check/-/custom-protocol-check-1.3.0.tgz", + "integrity": "sha512-ZhdszThJE9es2vja6N57cxaob79SDSCno0arWLKMv/Bc57zu8mZwPzkLl50sEA14G/Yd/HqWTXHH9HyMp9c5yA==" + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + }, + "dependencies": { + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "date-fns": { + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.2.tgz", + "integrity": "sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA==" + }, + "dayjs": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz", + "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==" + }, + "decimal.js": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.0.tgz", + "integrity": "sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "default-browser-id": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-1.0.4.tgz", + "integrity": "sha512-qPy925qewwul9Hifs+3sx1ZYn14obHxpkX+mPD369w4Rzg+YkJBgi3SOvwUq81nWSjqGUegIgEPwD8u+HUnxlw==", + "dev": true, + "optional": true, + "requires": { + "bplist-parser": "^0.1.0", + "meow": "^3.1.0", + "untildify": "^2.0.0" + } + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "requires": { + "execa": "^5.0.0" + }, + "dependencies": { + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + } + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } + }, + "detect-browser": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.3.0.tgz", + "integrity": "sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A==", + "requires": { + "repeating": "^2.0.0" + } + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "detect-package-manager": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-2.0.1.tgz", + "integrity": "sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==", + "dev": true, + "requires": { + "execa": "^5.1.1" + }, + "dependencies": { + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + } + } + }, + "detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" + }, + "diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==" + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==" + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "dns-packet": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", + "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, + "document.contains": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/document.contains/-/document.contains-1.0.2.tgz", + "integrity": "sha512-YcvYFs15mX8m3AO1QNQy3BlIpSMfNRj3Ujk2BEJxsZG+HZf7/hZ6jr7mDpXrF8q+ff95Vef5yjhiZxm8CGJr6Q==", + "requires": { + "define-properties": "^1.1.3" + } + }, + "dom-accessibility-api": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.3.0.tgz", + "integrity": "sha512-PzwHEmsRP3IGY4gv/Ug+rMeaTIyTJvadCb+ujYXYeIylbHJezIyNToe8KfEgHTCEYyC+/bUghYOGg8yMGlZ6vA==" + }, + "dom-align": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.3.tgz", + "integrity": "sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==" + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "requires": { + "utila": "~0.4" + } + }, + "dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "requires": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + } + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + } + } + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "requires": { + "webidl-conversions": "^4.0.2" + }, + "dependencies": { + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + } + } + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "requires": { + "domelementtype": "^2.3.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + } + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" + }, + "draft-js": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz", + "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==", + "requires": { + "fbjs": "^2.0.0", + "immutable": "~3.7.4", + "object-assign": "^4.1.1" + } + }, + "draft-js-export-markdown": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/draft-js-export-markdown/-/draft-js-export-markdown-1.4.0.tgz", + "integrity": "sha512-blfAvlhGhjVlHNaZ5WJKlrXhcftnwwC5VC+Eu3ztOGpGLaOom4hxhBjbKEWjvbQZJ9zL+xo57ukm39prYZMG5Q==", + "requires": { + "draft-js-utils": "^1.4.0" + } + }, + "draft-js-import-element": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/draft-js-import-element/-/draft-js-import-element-1.4.0.tgz", + "integrity": "sha512-WmYT5PrCm47lGL5FkH6sRO3TTAcn7qNHsD3igiPqLG/RXrqyKrqN4+wBgbcT2lhna/yfWTRtgzAbQsSJoS1Meg==", + "requires": { + "draft-js-utils": "^1.4.0", + "synthetic-dom": "^1.4.0" + } + }, + "draft-js-import-markdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/draft-js-import-markdown/-/draft-js-import-markdown-1.4.1.tgz", + "integrity": "sha512-58mDXJURrb5dsiN+cIms/gojI9jngE60WAwygYoxrEbsQeIIITOlFLjV/m/7Ko7HVpc5wjngVV2hzJ71T3FpMA==", + "requires": { + "draft-js-import-element": "^1.4.0", + "synthetic-dom": "^1.4.0" + } + }, + "draft-js-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/draft-js-utils/-/draft-js-utils-1.4.1.tgz", + "integrity": "sha512-xE81Y+z/muC5D5z9qWmKfxEW1XyXfsBzSbSBk2JRsoD0yzMGGHQm/0MtuqHl/EUDkaBJJLjJ2EACycoDMY/OOg==" + }, + "draftjs-utils": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.10.2.tgz", + "integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg==" + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.233", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.233.tgz", + "integrity": "sha512-ejwIKXTg1wqbmkcRJh9Ur3hFGHFDZDw1POzdsVrB2WZjgRuRMHIQQKNpe64N/qh3ZtH2otEoRoS+s6arAAuAAw==" + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==" + }, + "emoji-mart": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-3.0.1.tgz", + "integrity": "sha512-sxpmMKxqLvcscu6mFn9ITHeZNkGzIvD0BSNFE/LJESPbCA8s1jM6bCDPjWbV31xHq7JXaxgpHxLB54RCbBZSlg==", + "requires": { + "@babel/runtime": "^7.0.0", + "prop-types": "^15.6.0" + } + }, + "emoji-name-map": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/emoji-name-map/-/emoji-name-map-1.2.9.tgz", + "integrity": "sha512-MSM8y6koSqh/2uEMI2VoKA+Ac0qL5RkgFGP/pzL6n5FOrOJ7FOZFxgs7+uNpqA+AT+WmdbMPXkd3HnFXXdz4AA==", + "requires": { + "emojilib": "^2.0.2", + "iterate-object": "^1.3.1", + "map-o": "^2.0.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==" + }, + "emojione": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/emojione/-/emojione-4.5.0.tgz", + "integrity": "sha512-Tq55Y3UgPOnayFDN+Qd6QMP0rpoH10a1nhSFN27s8gXW3qymgFIHiXys2ECYYAI134BafmI3qP9ni2rZOe9BjA==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "endent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/endent/-/endent-2.1.0.tgz", + "integrity": "sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==", + "dev": true, + "requires": { + "dedent": "^0.7.0", + "fast-json-parse": "^1.0.3", + "objectorarray": "^1.0.5" + } + }, + "engine.io-client": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz", + "integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==", + "requires": { + "component-emitter": "~1.3.0", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.2.0", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "ws": "~7.4.2", + "xmlhttprequest-ssl": "~1.6.2", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" + } + } + }, + "engine.io-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", + "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "requires": { + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.4", + "blob": "0.0.5", + "has-binary2": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", + "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + } + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "enzyme": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", + "requires": { + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", + "has": "^1.0.3", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.2.1" + } + }, + "enzyme-adapter-react-16": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.6.tgz", + "integrity": "sha512-yFlVJCXh8T+mcQo8M6my9sPgeGzj85HSHi6Apgf1Cvq/7EL/J9+1JoJmJsRxZgyTvPMAqOEpRSu/Ii/ZpyOk0g==", + "requires": { + "enzyme-adapter-utils": "^1.14.0", + "enzyme-shallow-equal": "^1.0.4", + "has": "^1.0.3", + "object.assign": "^4.1.2", + "object.values": "^1.1.2", + "prop-types": "^15.7.2", + "react-is": "^16.13.1", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.7.0" + }, + "dependencies": { + "react-test-renderer": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.14.0.tgz", + "integrity": "sha512-L8yPjqPE5CZO6rKsKXRO/rVPiaCOy0tQQJbC+UjPNlobl5mad59lvPjwFsQHTvL03caVDIVr9x9/OSgDe6I5Eg==", + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.19.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "enzyme-adapter-utils": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.0.tgz", + "integrity": "sha512-F/z/7SeLt+reKFcb7597IThpDp0bmzcH1E9Oabqv+o01cID2/YInlqHbFl7HzWBl4h3OdZYedtwNDOmSKkk0bg==", + "requires": { + "airbnb-prop-types": "^2.16.0", + "function.prototype.name": "^1.1.3", + "has": "^1.0.3", + "object.assign": "^4.1.2", + "object.fromentries": "^2.0.3", + "prop-types": "^15.7.2", + "semver": "^5.7.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "enzyme-shallow-equal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", + "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", + "requires": { + "has": "^1.0.3", + "object-is": "^1.1.2" + } + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "requires": { + "stackframe": "^1.3.4" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es5-shim": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.7.tgz", + "integrity": "sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" + }, + "es6-shim": { + "version": "0.35.6", + "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", + "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==", + "dev": true + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "eslint": { + "version": "8.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz", + "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==", + "requires": { + "@eslint/eslintrc": "^1.3.1", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", + "@humanwhocodes/module-importer": "^1.0.1", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.4.0", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-react-app": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz", + "integrity": "sha512-pGIZ8t0mFLcV+6ZirRgYK6RVqUIKRIi9MmgzUEmrIknsn3AdO0I32asO86dJgloHq+9ZPl8UIg8mYrvgP5u2wQ==", + "requires": { + "confusing-browser-globals": "^1.0.9" + } + }, + "eslint-config-react-app-eslint-six": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-react-app-eslint-six/-/eslint-config-react-app-eslint-six-4.0.2.tgz", + "integrity": "sha512-g1UtZHhgr4LhFb2Qt/caLLevZHE9ayN7NxsflaDnTOY2y0EydrvrvYPie36/7ML1fe9q+av+Wg3r9k7cszIqBQ==", + "requires": { + "confusing-browser-globals": "^1.0.7" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "eslint-loader": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-3.0.3.tgz", + "integrity": "sha512-+YRqB95PnNvxNp1HEjQmvf9KNvCin5HXYYseOXVC2U0KEcw4IkQ2IQEBG46j7+gW39bMzeu0GsUhVbBY3Votpw==", + "requires": { + "fs-extra": "^8.1.0", + "loader-fs-cache": "^1.0.2", + "loader-utils": "^1.2.3", + "object-hash": "^2.0.1", + "schema-utils": "^2.6.1" + }, + "dependencies": { + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-plugin-flowtype": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.7.0.tgz", + "integrity": "sha512-M+hxhSCk5QBEValO5/UqrS4UunT+MgplIJK5wA1sCtXjzBcZkpTGRwxmLHhGpbHcrmQecgt6ZL/KDdXWqGB7VA==", + "requires": { + "lodash": "^4.17.15" + } + }, + "eslint-plugin-import": { + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", + "requires": { + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.1", + "find-up": "^2.0.0", + "has": "^1.0.3", + "is-core-module": "^2.4.0", + "minimatch": "^3.0.4", + "object.values": "^1.1.3", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "requires": { + "p-limit": "^1.1.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "eslint-plugin-jest": { + "version": "25.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", + "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0" + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz", + "integrity": "sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg==", + "requires": { + "@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" + }, + "dependencies": { + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + } + } + }, + "eslint-plugin-react": { + "version": "7.31.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.1.tgz", + "integrity": "sha512-j4/2xWqt/R7AZzG8CakGHA6Xa/u7iR8Q3xCxY+AUghdT92bnIDOBEefV456OeH0QvBcroVc0eyvrrLSyQGYIfg==", + "requires": { + "array-includes": "^3.1.5", + "array.prototype.flatmap": "^1.3.0", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.5", + "object.fromentries": "^2.0.5", + "object.hasown": "^1.1.1", + "object.values": "^1.1.5", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.3", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.7" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==" + }, + "eslint-plugin-storybook": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.5.13.tgz", + "integrity": "sha512-82x3FH1VAi68Awu1VEjn/hLkzFZsOP8ItcC5/uGF9WszIrj6n7Q3MZD57oE26k3aKwuPfFtAPnSjFnaBkBab+g==", + "dev": true, + "requires": { + "@storybook/csf": "^0.0.1", + "@typescript-eslint/experimental-utils": "^5.3.0", + "requireindex": "^1.1.0" + }, + "dependencies": { + "@storybook/csf": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.1.tgz", + "integrity": "sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + } + } + }, + "eslint-plugin-testing-library": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.6.0.tgz", + "integrity": "sha512-y63TRzPhGCMNsnUwMGJU1MFWc/3GvYw+nzobp9QiyNTTKsgAt5RKAOT1I34+XqVBpX1lC8bScoOjCkP7iRv0Mw==", + "requires": { + "@typescript-eslint/utils": "^5.13.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==" + }, + "eslint-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", + "requires": { + "@types/eslint": "^7.29.0 || ^8.4.1", + "jest-worker": "^28.0.2", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", + "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "espree": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz", + "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==", + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "estree-to-babel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/estree-to-babel/-/estree-to-babel-3.2.1.tgz", + "integrity": "sha512-YNF+mZ/Wu2FU/gvmzuWtYc8rloubL7wfXCTgouFrnjGVXPA/EeYYA7pupXWrb3Iv1cTBeSSxxJIbK23l4MRNqg==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.6", + "@babel/types": "^7.2.0", + "c8": "^7.6.0" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==" + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==", + "optional": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", + "optional": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "optional": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "optional": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==", + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "optional": true + } + } + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-parse": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", + "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "requires": { + "bser": "2.1.1" + } + }, + "fbjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz", + "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==", + "requires": { + "core-js": "^3.6.4", + "cross-fetch": "^3.0.4", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" + } + } + }, + "fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "feather-icons": { + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/feather-icons/-/feather-icons-4.29.0.tgz", + "integrity": "sha512-Y7VqN9FYb8KdaSF0qD1081HCkm0v4Eq/fpfQYQnubpqi0hXx14k+gF9iqtRys1SIcTEi97xDi/fmsPFZ8xo0GQ==", + "requires": { + "classnames": "^2.2.5", + "core-js": "^3.1.3" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" + } + } + }, + "fetch-polyfill": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fetch-polyfill/-/fetch-polyfill-0.8.2.tgz", + "integrity": "sha512-HnMXyMscl9drfxTsIgEBOgrEgFH1hq+223eCSQud7blPVhprK1ObBi0TA8KqGa7Ro22nrlwNz2XOtx9uwVXsCg==" + }, + "fetch-retry": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", + "integrity": "sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw==", + "dev": true + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.3.0.tgz", + "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==", + "requires": { + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "file-system-cache": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.1.0.tgz", + "integrity": "sha512-IzF5MBq+5CR0jXx5RxPe4BICl/oEhBSXKaL9fLhAXrIfIUS77Hr4vzrYyqYMHN6uTt+BOqi3fDCTjjEBCjERKw==", + "dev": true, + "requires": { + "fs-extra": "^10.1.0", + "ramda": "^0.28.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "ramda": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", + "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "dev": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==", + "optional": true + }, + "filesize": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.1.0.tgz", + "integrity": "sha512-LpCHtPQ3sFx67z+uh2HnSyWSLLu5Jxo21795uRDuar/EOuYWXib5EmPaGIBuSnRqH2IODiKA2k5re/K9OnN/Yg==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha512-Z9XSBoNE7xQiV6MSgPuCfyMokH2K7JdpRkOYE1+mu3d4BFJtx3GW+f6Bo4q8IX6rlf5MYbLBKW0pjl2cWdkm2A==", + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==" + }, + "flow-parser": { + "version": "0.185.2", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.185.2.tgz", + "integrity": "sha512-2hJ5ACYeJCzNtiVULov6pljKOLygy0zddoqSI1fFetM+XRPpRshFdGEijtqlamA1XwyZ+7rhryI6FQFzvtLWUQ==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "focus-lock": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-0.8.1.tgz", + "integrity": "sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "requires": { + "for-in": "^1.0.1" + } + }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" + }, + "fork-ts-checker-webpack-plugin": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", + "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "requires": { + "@babel/code-frame": "^7.5.5", + "chalk": "^2.4.1", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "semver": "^5.6.0", + "tapable": "^1.0.0", + "worker-rpc": "^0.1.0" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==" + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "fullcalendar": { + "version": "5.11.3", + "resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-5.11.3.tgz", + "integrity": "sha512-SgqiMEA+lWLyEd2jEwtIxdfx41j2CZr4KK00D2Gepj1MnGOjaEi13athnU6xvqMQXXjgJNj+vmlUP69QiuGncQ==" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "geojson-rbush": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-3.2.0.tgz", + "integrity": "sha512-oVltQTXolxvsz1sZnutlSuLDEcQAKYC/uXt9zDzJJ6bu0W+baTI8LZBaTup5afzibEH4N3jlq2p+a152wlBJ7w==", + "requires": { + "@turf/bbox": "*", + "@turf/helpers": "6.x", + "@turf/meta": "6.x", + "@types/geojson": "7946.0.8", + "rbush": "^3.0.1" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + }, + "get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==", + "dev": true, + "optional": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==", + "optional": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==", + "optional": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "optional": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-promise": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz", + "integrity": "sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==", + "dev": true, + "requires": { + "@types/glob": "*" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + } + } + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "gzip-size": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", + "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==", + "requires": { + "duplexer": "^0.1.1", + "pify": "^4.0.1" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "hamt_plus": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hamt_plus/-/hamt_plus-1.0.2.tgz", + "integrity": "sha512-t2JXKaehnMb9paaYA7J0BX8QQAY8lwfQ9Gjf4pg/mk4krt+cmwmU652HOoWonf+7+EQV97ARPMhhVgU1ra2GhA==" + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "harmony-reflect": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", + "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-binary2": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", + "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", + "requires": { + "isarray": "2.0.1" + }, + "dependencies": { + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" + } + } + }, + "has-cors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", + "integrity": "sha512-g5VNKdkFuUuVCP9gYfDJHjK2nqdQJ7aDLTnycnc2+RvsOQbuLdF5pm7vuE5J76SEBIQjs4kQY/BWq74JUmjbXA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", + "integrity": "sha512-D+8A457fBShSEI3tFCj65PAbT++5sKiFtdCdOam0gnfBgw9D277OERk+HM9qYJXmdVLZ/znez10SqHN0BBQ50g==", + "dev": true, + "requires": { + "is-glob": "^3.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "dev": true, + "requires": { + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "dev": true + }, + "hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "dev": true, + "requires": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "dev": true, + "requires": { + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + } + }, + "hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "dev": true, + "requires": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==" + }, + "highlight-words-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz", + "integrity": "sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==" + }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + }, + "history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "requires": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "requires": { + "react-is": "^16.7.0" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha512-ycURW7oUxE2sNiPVw1HVEFsW+ecOpJ5zaj7eC0RlwhibhRBod20muUN8qu/gzx956YrLolVvs1MTXwKgC2rVEg==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "hoopy": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", + "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==" + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==" + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==" + }, + "html-element-map": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz", + "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==", + "requires": { + "array.prototype.filter": "^1.0.0", + "call-bind": "^1.0.2" + } + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==" + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + } + } + }, + "html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "requires": { + "void-elements": "3.1.0" + } + }, + "html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "dev": true + }, + "html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", + "dev": true + }, + "html-webpack-plugin": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", + "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", + "requires": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + }, + "dependencies": { + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + } + } + }, + "htmlparser2": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz", + "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "entities": "^4.3.0" + }, + "dependencies": { + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domutils": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", + "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.1" + } + }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==" + } + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz", + "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==", + "requires": { + "@types/http-proxy": "^1.17.5", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, + "i18next": { + "version": "20.6.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-20.6.1.tgz", + "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==", + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "i18next-browser-languagedetector": { + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-6.1.5.tgz", + "integrity": "sha512-11t7b39oKeZe4uyMxLSPnfw28BCPNLZgUk7zyufex0zKXZ+Bv+JnmJgoB+IfQLZwDt1d71PM8vwBX1NCgliY3g==", + "requires": { + "@babel/runtime": "^7.18.9" + } + }, + "i18next-http-backend": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-1.4.1.tgz", + "integrity": "sha512-s4Q9hK2jS29iyhniMP82z+yYY8riGTrWbnyvsSzi5TaF7Le4E7b5deTmtuaRuab9fdDcYXtcwdBgawZG+JCEjA==", + "requires": { + "cross-fetch": "3.1.5" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "requires": { + "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "idb": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.2.tgz", + "integrity": "sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==" + }, + "idb-wrapper": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/idb-wrapper/-/idb-wrapper-1.7.2.tgz", + "integrity": "sha512-zfNREywMuf0NzDo9mVsL0yegjsirJxHpKHvWcyRozIqQy89g0a3U+oBPOCN4cc0oCiOuYgZHimzaW/R46G1Mpg==" + }, + "identity-obj-proxy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", + "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", + "requires": { + "harmony-reflect": "^1.4.6" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==" + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "optional": true + }, + "immer": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz", + "integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA==" + }, + "immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==" + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==", + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==", + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" + } + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==" + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg==" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "dev": true + }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==" + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==", + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==" + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", + "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==", + "dev": true, + "requires": { + "is-object": "^1.0.1", + "is-window": "^1.0.2" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==", + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==", + "optional": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true + }, + "is-in-browser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-in-browser/-/is-in-browser-1.1.3.tgz", + "integrity": "sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==" + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==", + "optional": true + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==", + "optional": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==" + }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==" + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true, + "optional": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true + }, + "is-window": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", + "integrity": "sha512-uj00kdXyZb9t9RcAUAwMZAnkBUwdYGhYlt7djMXhfyhUCzwNba50tIiBKR7q0l7tdoBtFVw/3JmLY6fI3rmZmg==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "dev": true, + "requires": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==" + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "dev": true + }, + "iterate-object": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/iterate-object/-/iterate-object-1.3.4.tgz", + "integrity": "sha512-4dG1D1x/7g8PwHS9aK6QV5V94+ZvyP4+d19qDv43EzImmrndysIl4prmJ1hWWIGCqrZHyaHBm6BSEWHOLnpoNw==" + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + } + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "dependencies": { + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + } + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" + } + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tough-cookie": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", + "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "requires": { + "punycode": "^2.1.1" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" + } + } + }, + "jest-environment-jsdom-fourteen": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-1.0.1.tgz", + "integrity": "sha512-DojMX1sY+at5Ep+O9yME34CdidZnO3/zfPh8UW+918C5fIZET5vCjfkegixmsi7AtdYfkr4bPlIzmWnlvQkP7Q==", + "requires": { + "@jest/environment": "^24.3.0", + "@jest/fake-timers": "^24.3.0", + "@jest/types": "^24.3.0", + "jest-mock": "^24.0.0", + "jest-util": "^24.0.0", + "jsdom": "^14.1.0" + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "dependencies": { + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==" + }, + "jest-haste-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", + "requires": { + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", + "fb-watchman": "^2.0.0", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "optional": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "jest-matcher-utils": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", + "requires": { + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-message-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "jest-mock": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", + "requires": { + "@jest/types": "^24.9.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" + }, + "jest-regex-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==" + }, + "jest-resolve": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", + "requires": { + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", + "jest-pnp-resolver": "^1.2.1", + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==" + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-watch-typeahead": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.6.1.tgz", + "integrity": "sha512-ITVnHhj3Jd/QkqQcTqZfRgjfyRhDFM/auzgVo2RKvSwi18YMvh0WvXDJFoFED6c7jd/5jxtu4kSOb9PTu2cPVg==", + "requires": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^26.0.0", + "jest-watcher": "^26.3.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-watcher": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz", + "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==", + "requires": { + "@jest/test-result": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^26.6.2", + "string-length": "^4.0.1" + }, + "dependencies": { + "@jest/console": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz", + "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==", + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^26.6.2", + "jest-util": "^26.6.2", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz", + "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==", + "requires": { + "@jest/console": "^26.6.2", + "@jest/types": "^26.6.2", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-message-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz", + "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.6.2", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "pretty-format": "^26.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "requires": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "jquery": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz", + "integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==" + }, + "js-sha1": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/js-sha1/-/js-sha1-0.6.0.tgz", + "integrity": "sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==" + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "jscodeshift": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", + "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", + "dev": true, + "requires": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^3.1.10", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.20.4", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "dependencies": { + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "recast": { + "version": "0.20.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", + "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "dev": true, + "requires": { + "ast-types": "0.14.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + } + } + }, + "jsdom": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", + "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.1.3", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==" + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==", + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "requires": { + "string-convert": "^0.2.0" + } + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==" + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + } + }, + "jss": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss/-/jss-10.9.2.tgz", + "integrity": "sha512-b8G6rWpYLR4teTUbGd4I4EsnWjg7MN0Q5bSsjKhVkJVjhQDy2KzkbD2AW3TuT0RYZVmZZHKIrXDn6kjU14qkUg==", + "requires": { + "@babel/runtime": "^7.3.1", + "csstype": "^3.0.2", + "is-in-browser": "^1.1.3", + "tiny-warning": "^1.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + } + } + }, + "jss-plugin-camel-case": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.2.tgz", + "integrity": "sha512-wgBPlL3WS0WDJ1lPJcgjux/SHnDuu7opmgQKSraKs4z8dCCyYMx9IDPFKBXQ8Q5dVYij1FFV0WdxyhuOOAXuTg==", + "requires": { + "@babel/runtime": "^7.3.1", + "hyphenate-style-name": "^1.0.3", + "jss": "10.9.2" + } + }, + "jss-plugin-default-unit": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-default-unit/-/jss-plugin-default-unit-10.9.2.tgz", + "integrity": "sha512-pYg0QX3bBEFtTnmeSI3l7ad1vtHU42YEEpgW7pmIh+9pkWNWb5dwS/4onSfAaI0kq+dOZHzz4dWe+8vWnanoSg==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.9.2" + } + }, + "jss-plugin-global": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-global/-/jss-plugin-global-10.9.2.tgz", + "integrity": "sha512-GcX0aE8Ef6AtlasVrafg1DItlL/tWHoC4cGir4r3gegbWwF5ZOBYhx04gurPvWHC8F873aEGqge7C17xpwmp2g==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.9.2" + } + }, + "jss-plugin-nested": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-nested/-/jss-plugin-nested-10.9.2.tgz", + "integrity": "sha512-VgiOWIC6bvgDaAL97XCxGD0BxOKM0K0zeB/ECyNaVF6FqvdGB9KBBWRdy2STYAss4VVA7i5TbxFZN+WSX1kfQA==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.9.2", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-props-sort": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-props-sort/-/jss-plugin-props-sort-10.9.2.tgz", + "integrity": "sha512-AP1AyUTbi2szylgr+O0OB7gkIxEGzySLITZ2GpsaoX72YMCGI2jYAc+WUhPfvUnZYiauF4zTnN4V4TGuvFjJlw==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.9.2" + } + }, + "jss-plugin-rule-value-function": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.9.2.tgz", + "integrity": "sha512-vf5ms8zvLFMub6swbNxvzsurHfUZ5Shy5aJB2gIpY6WNA3uLinEcxYyraQXItRHi5ivXGqYciFDRM2ZoVoRZ4Q==", + "requires": { + "@babel/runtime": "^7.3.1", + "jss": "10.9.2", + "tiny-warning": "^1.0.2" + } + }, + "jss-plugin-vendor-prefixer": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.9.2.tgz", + "integrity": "sha512-SxcEoH+Rttf9fEv6KkiPzLdXRmI6waOTcMkbbEFgdZLDYNIP9UKNHFy6thhbRKqv0XMQZdrEsbDyV464zE/dUA==", + "requires": { + "@babel/runtime": "^7.3.1", + "css-vendor": "^2.0.8", + "jss": "10.9.2" + } + }, + "jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "requires": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + } + }, + "junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true + }, + "just-reduce-object": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/just-reduce-object/-/just-reduce-object-1.2.1.tgz", + "integrity": "sha512-/3ov68tJlesyccBgilcd5wDAOEZJ10NyhVa5pkUMbH0lC/NBBGfPewn1CUZNXecX5zgZqQVIO7MAi1whbYhVFg==" + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==" + }, + "language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==" + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==" + }, + "lazy-universal-dotenv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", + "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.0", + "app-root-dir": "^1.0.2", + "core-js": "^3.0.4", + "dotenv": "^8.0.0", + "dotenv-expand": "^5.1.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==", + "dev": true + } + } + }, + "less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "optional": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "less-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-7.3.0.tgz", + "integrity": "sha512-Mi8915g7NMaLlgi77mgTTQvK022xKRQBIVDSyfl3ErTuBhmZBQab0mjeJjNNqGbdR+qrfTleKXqbGI4uEFavxg==", + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==" + }, + "line-height": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/line-height/-/line-height-0.1.1.tgz", + "integrity": "sha512-JDIlrJycHpYS1bY1sDwlqmOaouI2lzLXvwqitRrf+AJXpvkWUK4m0Hz6TK7F7xZSarWOMEPMN7LxsjUHU+UEpg==", + "requires": { + "computed-style": "~0.1.3" + } + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + } + } + }, + "load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==" + }, + "loader-fs-cache": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz", + "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==", + "requires": { + "find-cache-dir": "^0.1.1", + "mkdirp": "^0.5.1" + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==" + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==" + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==" + }, + "loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==", + "dev": true, + "optional": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "requires": { + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "dev": true + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "requires": { + "tmpl": "1.0.5" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + }, + "map-o": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/map-o/-/map-o-2.0.10.tgz", + "integrity": "sha512-BxazE81fVByHWasyXhqKeo2m7bFKYu+ZbEfiuexMOnklXW+tzDvnlTi/JaklEeuuwqcqJzPaf9q+TWptSGXeLg==", + "requires": { + "iterate-object": "^1.3.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "optional": true + }, + "map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-draft-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/markdown-draft-js/-/markdown-draft-js-2.4.0.tgz", + "integrity": "sha512-MalOqajYYaELKLPHLnUcaU7kwhIHveVdKd15SKBkDkWj1NBLHuM5uZjXQ5TDfM4rrk4tcAzIvwWhCJzdGNcmkg==", + "requires": { + "remarkable": "^2.0.1" + } + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true + }, + "markdown-to-jsx": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz", + "integrity": "sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w==" + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "optional": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "dev": true, + "requires": { + "unist-util-remove": "^2.0.0" + } + }, + "mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "dev": true, + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + } + } + }, + "memfs": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", + "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", + "requires": { + "fs-monkey": "^1.0.3" + } + }, + "memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==" + }, + "memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "requires": { + "map-or-similar": "^1.5.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==", + "dev": true, + "optional": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "optional": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==", + "dev": true, + "optional": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "optional": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "optional": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "optional": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "optional": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==", + "dev": true, + "optional": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "optional": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==", + "dev": true, + "optional": true, + "requires": { + "get-stdin": "^4.0.1" + } + } + } + }, + "merge-deep": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.3.tgz", + "integrity": "sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA==", + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", + "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==" + }, + "mini-create-react-context": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", + "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", + "requires": { + "@babel/runtime": "^7.12.1", + "tiny-warning": "^1.0.3" + } + }, + "mini-css-extract-plugin": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.12.0.tgz", + "integrity": "sha512-z6PQCe9rd1XUwZ8gMaEVwwRyZlrYy8Ba1gRjFP5HcV51HkXX+XlwZ+a1iAYTjSYwgNBXoNR7mhx79mDpOn5fdw==", + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==" + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minimongo": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/minimongo/-/minimongo-6.12.6.tgz", + "integrity": "sha512-i1t7z9H3F0d7v0EsfN7QFOxM99vR/6BmvPtBjfdUGhgekRdI0EYRCBCxl0VwOPnCFeADzCPvkiuXCEFiVysUCg==", + "requires": { + "@turf/boolean-crosses": "^6.0.1", + "@turf/boolean-point-in-polygon": "^6.0.1", + "@turf/boolean-within": "^6.0.1", + "@turf/intersect": "^6.1.3", + "async": "^1.4.2", + "bowser": "^0.7.1", + "idb-wrapper": "^1.4.1", + "jquery": "^3.6.0", + "js-sha1": "^0.6.0", + "lodash": "^4.0.0" + } + }, + "minipass": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", + "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha512-ALGF1Jt9ouehcaXaHhn6t1yGWRqGaHkPFndtFVHfZXOvkIZ/yoGaSi0AHVTafb3ZBGg4dr/bDwnaEKqCXzchMA==", + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha512-F0to7vbBSHP8E3l6dCjxNOLuSFAACIxFy3UehTUlG7svlXi37HHsDkyVcHo0Pq8QwrE+pXvWSVX3ZT1T9wAZ9g==" + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "moment-timezone": { + "version": "0.5.37", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.37.tgz", + "integrity": "sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "native-url": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/native-url/-/native-url-0.2.6.tgz", + "integrity": "sha512-k4bDC87WtgrdD362gZz6zoiXQrl40kYlBmpfmSjwRO1VU0V5ccwJTlxuE72F6m3V0vc1xOf6n3UCP9QyerRqmA==", + "dev": true, + "requires": { + "querystring": "^0.2.0" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + } + }, + "needle": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", + "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nested-error-stacks": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "dev": true, + "requires": { + "minimatch": "^3.0.2" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + } + } + } + } + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==" + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==", + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "requires": { + "path-key": "^2.0.0" + }, + "dependencies": { + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + } + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==" + }, + "nwsapi": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", + "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz", + "integrity": "sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==", + "requires": { + "array.prototype.reduce": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.1" + } + }, + "object.hasown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.1.tgz", + "integrity": "sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==", + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==", + "optional": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "objectorarray": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/objectorarray/-/objectorarray-1.0.5.tgz", + "integrity": "sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==", + "dev": true + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "oidc-client": { + "version": "1.11.5", + "resolved": "https://registry.npmjs.org/oidc-client/-/oidc-client-1.11.5.tgz", + "integrity": "sha512-LcKrKC8Av0m/KD/4EFmo9Sg8fSQ+WFJWBrmtWd+tZkNn3WT/sQG3REmPANE9tzzhbjW6VkTNy4xhAXCfPApAOg==", + "requires": { + "acorn": "^7.4.1", + "base64-js": "^1.5.1", + "core-js": "^3.8.3", + "crypto-js": "^4.0.0", + "serialize-javascript": "^4.0.0" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" + } + } + }, + "oidc-react": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/oidc-react/-/oidc-react-1.5.1.tgz", + "integrity": "sha512-rbNfWUBRiqolht9J5tRu5HktDs8yXii1KfOBXtM9uwQNaiY0UgvIzl2h7NNOYA04TFxKtGlXkwrs9cPn28JwEg==", + "requires": { + "oidc-client": "^1.11.5" + } + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "requires": { + "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" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha512-uQLlclru4xpCi+tfs80l3QF24KL81X57ELNMy7W/dox+JTtxUf1bLyQ8968fFCmSqqbokjW0kn+WBIlO+rSkNg==", + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, + "p-all": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", + "integrity": "sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==", + "dev": true, + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "dev": true + }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "requires": { + "p-timeout": "^3.1.0" + } + }, + "p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + } + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==" + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==", + "optional": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "optional": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, + "parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "requires": { + "entities": "^4.3.0" + }, + "dependencies": { + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==" + } + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "requires": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + } + }, + "parseqs": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", + "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" + }, + "parseuri": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", + "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==" + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + } + } + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "perfect-scrollbar": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/perfect-scrollbar/-/perfect-scrollbar-1.5.5.tgz", + "integrity": "sha512-dzalfutyP3e/FOpdlhVryN4AJ5XDVauVWxybSkLZmakFE2sS3y3pc4JnSprw8tGmHvkaG5Edr5T7LBTZ+WWU2g==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==" + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha512-c6pv3OE78mcZ92ckebVDqg0aWSoKhOTbwCV6qbCWMk546mAL9pZln0+QsN/yQ7fkucd4+yJPLrCBXNt8Ruk+Eg==", + "requires": { + "find-up": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha512-fjAPuiws93rm7mPUu21RdBnkeZNrbfCFCwfAhPWY+rR3zG0ubpe5cEReHOw5fIbfmsxEV/g2kSxGTATY3Bpnwg==", + "requires": { + "find-up": "^2.1.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "requires": { + "p-limit": "^1.1.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "platform": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==" + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "polished": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.17.8" + } + }, + "polygon-clipping": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/polygon-clipping/-/polygon-clipping-0.15.3.tgz", + "integrity": "sha512-ho0Xx5DLkgxRx/+n4O74XyJ67DcyN3Tu9bGYKsnTukGAW6ssnuak6Mwcyb1wHy9MZc9xsUWqIoiazkZB5weECg==", + "requires": { + "splaytree": "^3.1.0" + } + }, + "popper.js": { + "version": "1.16.1-lts", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1-lts.tgz", + "integrity": "sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" + }, + "postcss": { + "version": "8.4.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", + "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-browser-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz", + "integrity": "sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig==", + "requires": { + "postcss": "^7" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-clamp": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", + "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "requires": { + "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-flexbugs-fixes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", + "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", + "requires": { + "postcss": "^7.0.26" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-font-variant": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz", + "integrity": "sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz", + "integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==" + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-8.0.1.tgz", + "integrity": "sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ==", + "requires": { + "@csstools/normalize.css": "^10.1.0", + "browserslist": "^4.6.2", + "postcss": "^7.0.17", + "postcss-browser-comments": "^3.0.0", + "sanitize.css": "^10.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "requires": { + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-opacity-percentage": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", + "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==" + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==" + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "requires": { + "postcss": "^7.0.26" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-selector-not": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz", + "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==", + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==", + "optional": true + }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "~2.0.3" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" + }, + "promise.allsettled": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.5.tgz", + "integrity": "sha512-tVDqeZPoBC0SlzJHzWGZ2NKAguVq2oiYj7gbggbiTvH2itHohijTp7njOUA0aQ/nl+0lr/r6egmhoYu63UZ/pQ==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "iterate-value": "^1.0.2" + } + }, + "promise.prototype.finally": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz", + "integrity": "sha512-EXRF3fC9/0gz4qkt/f5EP5iW4kj9oFpBICNpCNOb/52+8nlHIX07FPLbi/q4qYBQ1xZqivMzTpNQSnArVASolQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "prompts": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz", + "integrity": "sha512-awZAKrk3vN6CroQukBL+R9051a4R3zCZBlJm/HBfrSZ8iTpYix3VX1vU4mveiLpiwmOJT4wokTF9m6HUk4KqWQ==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, + "property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==" + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "puppeteer-core": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.1.1.tgz", + "integrity": "sha512-n13AWriBMPYxnpbb6bnaY5YoY6rGj8vPLrz6CZF3o0qJNEwlcfJVxBzYZ0NJsQ21UbdJoijPCDrM++SUVEz7+w==", + "dev": true, + "requires": { + "@types/mime-types": "^2.1.0", + "debug": "^4.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^4.0.0", + "mime": "^2.0.3", + "mime-types": "^2.1.25", + "progress": "^2.0.1", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^6.1.0" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==" + }, + "qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==", + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" + }, + "quickselect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", + "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==" + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "requires": { + "performance-now": "^2.1.0" + } + }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==" + }, + "ramda": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz", + "integrity": "sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ==" + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "optional": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "optional": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "optional": true + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "rbush": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", + "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", + "requires": { + "quickselect": "^2.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + } + } + }, + "rc-align": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.12.tgz", + "integrity": "sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "dom-align": "^1.7.0", + "lodash": "^4.17.21", + "rc-util": "^5.3.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-cascader": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.6.2.tgz", + "integrity": "sha512-sf2otpazlROTzkD3nZVfIzXmfBLiEOBTXA5wxozGXBpS902McDpvF0bdcYBu5hN+rviEAm6Mh9cLXNQ1Ty8wKQ==", + "requires": { + "@babel/runtime": "^7.12.5", + "array-tree-filter": "^2.1.0", + "classnames": "^2.3.1", + "rc-select": "~14.1.0", + "rc-tree": "~5.6.3", + "rc-util": "^5.6.1" + } + }, + "rc-checkbox": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.3.2.tgz", + "integrity": "sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-collapse": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.3.1.tgz", + "integrity": "sha512-cOJfcSe3R8vocrF8T+PgaHDrgeA1tX+lwfhwSj60NX9QVRidsILIbRNDLD6nAzmcvVC5PWiIRiR4S1OobxdhCg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.2.1", + "shallowequal": "^1.1.0" + } + }, + "rc-dialog": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-8.9.0.tgz", + "integrity": "sha512-Cp0tbJnrvPchJfnwIvOMWmJ4yjX3HWFatO6oBFD1jx8QkgsQCR0p8nUWAKdd3seLJhEC39/v56kZaEjwp9muoQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + } + }, + "rc-drawer": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-5.1.0.tgz", + "integrity": "sha512-pU3Tsn99pxGdYowXehzZbdDVE+4lDXSGb7p8vA9mSmr569oc2Izh4Zw5vLKSe/Xxn2p5MSNbLVqD4tz+pK6SOw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.21.2" + } + }, + "rc-dropdown": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.0.1.tgz", + "integrity": "sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.6", + "rc-trigger": "^5.3.1", + "rc-util": "^5.17.0" + } + }, + "rc-field-form": { + "version": "1.27.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.27.1.tgz", + "integrity": "sha512-RShegnwFu6TH8tl2olCxn+B4Wyh5EiQH8c/7wucbkLNyue05YiH5gomUAg1vbZjp71yFKwegClctsEG5CNBWAA==", + "requires": { + "@babel/runtime": "^7.18.0", + "async-validator": "^4.1.0", + "rc-util": "^5.8.0" + } + }, + "rc-image": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-5.7.1.tgz", + "integrity": "sha512-QyMfdhoUfb5W14plqXSisaYwpdstcLYnB0MjX5ccIK2rydQM9sDPuekQWu500DDGR2dBaIF5vx9XbWkNFK17Fg==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-dialog": "~8.9.0", + "rc-util": "^5.0.6" + } + }, + "rc-input": { + "version": "0.0.1-alpha.7", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-0.0.1-alpha.7.tgz", + "integrity": "sha512-eozaqpCYWSY5LBMwlHgC01GArkVEP+XlJ84OMvdkwUnJBSv83Yxa15pZpn7vACAj84uDC4xOA2CoFdbLuqB08Q==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + } + }, + "rc-input-number": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-7.3.6.tgz", + "integrity": "sha512-Se62oMOBn9HwF/gSag+YtAYyKZsjJzEsqmyAJHAnAvPfjZJOu7dLMlQRwBbTtELbKXM/Y5Fztcq8CW2Y9f49qA==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.23.0" + } + }, + "rc-mentions": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-1.9.2.tgz", + "integrity": "sha512-uxb/lzNnEGmvraKWNGE6KXMVXvt8RQv9XW8R0Dqi3hYsyPiAZeHRCHQKdLARuk5YBhFhZ6ga55D/8XuY367g3g==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-menu": "~9.6.0", + "rc-textarea": "^0.3.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.22.5" + } + }, + "rc-menu": { + "version": "9.6.3", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.6.3.tgz", + "integrity": "sha512-KY9QilKWgkJZ0JSpOBgIpQF2wMRRodRxpIMYyIJ3Nd5N6xfVLOxXCxevHcBplt+Ez7MhUF+I03MuAKqWQJLZgw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.2.0", + "rc-trigger": "^5.1.2", + "rc-util": "^5.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-motion": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.6.2.tgz", + "integrity": "sha512-4w1FaX3dtV749P8GwfS4fYnFG4Rb9pxvCYPc/b2fw1cmlHJWNNgOFIz7ysiD+eOrzJSvnLJWlNQQncpNMXwwpg==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.21.0" + } + }, + "rc-notification": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-4.6.0.tgz", + "integrity": "sha512-xF3MKgIoynzjQAO4lqsoraiFo3UXNYlBfpHs0VWvwF+4pimen9/H1DYLN2mfRWhHovW6gRpla73m2nmyIqAMZQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.2.0", + "rc-util": "^5.20.1" + } + }, + "rc-overflow": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.2.8.tgz", + "integrity": "sha512-QJ0UItckWPQ37ZL1dMEBAdY1dhfTXFL9k6oTTcyydVwoUNMnMqCGqnRNA98axSr/OeDKqR6DVFyi8eA5RQI/uQ==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.19.2" + } + }, + "rc-pagination": { + "version": "3.1.17", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.1.17.tgz", + "integrity": "sha512-/BQ5UxcBnW28vFAcP2hfh+Xg15W0QZn8TWYwdCApchMH1H0CxiaUUcULP8uXcFM1TygcdKWdt3JqsL9cTAfdkQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1" + } + }, + "rc-picker": { + "version": "2.6.10", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-2.6.10.tgz", + "integrity": "sha512-9wYtw0DFWs9FO92Qh2D76P0iojUr8ZhLOtScUeOit6ks/F+TBLrOC1uze3IOu+u9gbDAjmosNWLKbBzx/Yuv2w==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "date-fns": "2.x", + "dayjs": "1.x", + "moment": "^2.24.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.4.0", + "shallowequal": "^1.1.0" + } + }, + "rc-progress": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.3.3.tgz", + "integrity": "sha512-MDVNVHzGanYtRy2KKraEaWeZLri2ZHWIRyaE1a9MQ2MuJ09m+Wxj5cfcaoaR6z5iRpHpA59YeUxAlpML8N4PJw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + } + }, + "rc-rate": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.9.2.tgz", + "integrity": "sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + } + }, + "rc-resize-observer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.2.0.tgz", + "integrity": "sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.15.0", + "resize-observer-polyfill": "^1.5.1" + } + }, + "rc-segmented": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.1.0.tgz", + "integrity": "sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw==", + "requires": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + } + }, + "rc-select": { + "version": "14.1.9", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.1.9.tgz", + "integrity": "sha512-DK01+Q7oCWr5jVPiEp/BTQ8xCB4rI4LfXzZtSmBWJhOMuibyZD1Vlz/DlVKCUFmtBM4SzG4/SltGHoGlcbCqiw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.0.0", + "rc-trigger": "^5.0.4", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.2.0" + } + }, + "rc-slider": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.0.1.tgz", + "integrity": "sha512-igTKF3zBet7oS/3yNiIlmU8KnZ45npmrmHlUUio8PNbIhzMcsh+oE/r2UD42Y6YD2D/s+kzCQkzQrPD6RY435Q==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.18.1", + "shallowequal": "^1.1.0" + } + }, + "rc-steps": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-4.1.4.tgz", + "integrity": "sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==", + "requires": { + "@babel/runtime": "^7.10.2", + "classnames": "^2.2.3", + "rc-util": "^5.0.1" + } + }, + "rc-switch": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-3.2.2.tgz", + "integrity": "sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.0.1" + } + }, + "rc-table": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.25.3.tgz", + "integrity": "sha512-McsLJ2rg8EEpRBRYN4Pf9gT7ZNYnjvF9zrBpUBBbUX/fxk+eGi5ff1iPIhMyiHsH71/BmTUzX9nc9XqupD0nMg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.22.5", + "shallowequal": "^1.1.0" + } + }, + "rc-tabs": { + "version": "11.16.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-11.16.1.tgz", + "integrity": "sha512-bR7Dap23YyfzZQwtKomhiFEFzZuE7WaKWo+ypNRSGB9PDKSc6tM12VP8LWYkvmmQHthgwP0WRN8nFbSJWuqLYw==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.0.0", + "rc-menu": "~9.6.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.5.0" + } + }, + "rc-textarea": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-0.3.7.tgz", + "integrity": "sha512-yCdZ6binKmAQB13hc/oehh0E/QRwoPP1pjF21aHBxlgXO3RzPF6dUu4LG2R4FZ1zx/fQd2L1faktulrXOM/2rw==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.7.0", + "shallowequal": "^1.1.0" + } + }, + "rc-tooltip": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.2.2.tgz", + "integrity": "sha512-jtQzU/18S6EI3lhSGoDYhPqNpWajMtS5VV/ld1LwyfrDByQpYmw/LW6U7oFXXLukjfDHQ7Ju705A82PRNFWYhg==", + "requires": { + "@babel/runtime": "^7.11.2", + "classnames": "^2.3.1", + "rc-trigger": "^5.0.0" + } + }, + "rc-tree": { + "version": "5.6.6", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.6.6.tgz", + "integrity": "sha512-HI/q4D4AHOp48OZcBUvJFWkI5OfnZivvGYI0xzI0dy0Mita2KcTGZv7/Yl6Aq3bL3od3x5AqAXq/7qxR3x4Kkg==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.4.8" + } + }, + "rc-tree-select": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.4.1.tgz", + "integrity": "sha512-xhXnKP8Stu2Q7wTcjJaSzSOLd4wmFtUZOwmy1cioaWyPbpiKlYdnALXA/9U49HOaV3KFXdRHE9Yi0KYED7yOAQ==", + "requires": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "~14.1.0", + "rc-tree": "~5.6.1", + "rc-util": "^5.16.1" + } + }, + "rc-trigger": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.1.tgz", + "integrity": "sha512-5gaFbDkYSefZ14j2AdzucXzlWgU2ri5uEjkHvsf1ynRhdJbKxNOnw4PBZ9+FVULNGFiDzzlVF8RJnR9P/xrnKQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.6", + "rc-align": "^4.0.0", + "rc-motion": "^2.0.0", + "rc-util": "^5.19.2" + } + }, + "rc-upload": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.4.tgz", + "integrity": "sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==", + "requires": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + } + }, + "rc-util": { + "version": "5.23.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.23.0.tgz", + "integrity": "sha512-lgm6diJ/pLgyfoZY59Vz7sW4mSoQCgozqbBye9IJ7/mb5w5h4T7h+i2JpXAx/UBQxscBZe68q0sP7EW+qfkKUg==", + "requires": { + "@babel/runtime": "^7.18.3", + "react-is": "^16.12.0", + "shallowequal": "^1.1.0" + } + }, + "rc-virtual-list": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.4.8.tgz", + "integrity": "sha512-qSN+Rv4i/E7RCTvTMr1uZo7f3crJJg/5DekoCagydo9zsXrxj07zsFSxqizqW+ldGA16lwa8So/bIbV9Ofjddg==", + "requires": { + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.15.0" + } + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-ace": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-9.5.0.tgz", + "integrity": "sha512-4l5FgwGh6K7A0yWVMQlPIXDItM4Q9zzXRqOae8KkCl6MkOob7sC1CzHxZdOGvV+QioKWbX2p5HcdOVUv6cAdSg==", + "requires": { + "ace-builds": "^1.4.13", + "diff-match-patch": "^1.0.5", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.7.2" + } + }, + "react-app-polyfill": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz", + "integrity": "sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==", + "requires": { + "core-js": "^3.5.0", + "object-assign": "^4.1.1", + "promise": "^8.0.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.3", + "whatwg-fetch": "^3.0.0" + }, + "dependencies": { + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" + }, + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "requires": { + "asap": "~2.0.6" + } + } + } + }, + "react-beautiful-dnd": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-10.1.0.tgz", + "integrity": "sha512-oij2ZLIQ6SFmqy/MiXbuO8HUFHQ39gaPsTYj0Ewk0XwbLM32L+diVP0NXbEK7nhYv5lF2jviXGnda+BYMi6+nA==", + "requires": { + "@babel/runtime-corejs2": "^7.3.4", + "css-box-model": "^1.1.1", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.1", + "raf-schd": "^4.0.0", + "react-redux": "^5.0.7", + "redux": "^4.0.1", + "tiny-invariant": "^1.0.3" + }, + "dependencies": { + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, + "react-redux": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz", + "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==", + "requires": { + "@babel/runtime": "^7.1.2", + "hoist-non-react-statics": "^3.3.0", + "invariant": "^2.2.4", + "loose-envify": "^1.1.0", + "prop-types": "^15.6.1", + "react-is": "^16.6.0", + "react-lifecycles-compat": "^3.0.0" + } + } + } + }, + "react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "requires": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + } + }, + "react-dev-utils": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.4.tgz", + "integrity": "sha512-dx0LvIGHcOPtKbeiSUM4jqpBl3TcY7CDjZdfOIcKeznE7BWr9dg0iPG90G5yfVQ+p/rGNMXdbfStvzQZEVEi4A==", + "requires": { + "@babel/code-frame": "7.10.4", + "address": "1.1.2", + "browserslist": "4.14.2", + "chalk": "2.4.2", + "cross-spawn": "7.0.3", + "detect-port-alt": "1.1.6", + "escape-string-regexp": "2.0.0", + "filesize": "6.1.0", + "find-up": "4.1.0", + "fork-ts-checker-webpack-plugin": "4.1.6", + "global-modules": "2.0.0", + "globby": "11.0.1", + "gzip-size": "5.1.1", + "immer": "8.0.1", + "is-root": "2.1.0", + "loader-utils": "2.0.0", + "open": "^7.0.2", + "pkg-up": "3.1.0", + "prompts": "2.4.0", + "react-error-overlay": "^6.0.9", + "recursive-readdir": "2.2.2", + "shell-quote": "1.7.2", + "strip-ansi": "6.0.0", + "text-table": "0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "browserslist": { + "version": "4.14.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.2.tgz", + "integrity": "sha512-HI4lPveGKUR0x2StIz+2FXfDk9SfVMrxn6PLh1JeGUwcuoDkdKZebWiyLRJ68iIPDpMI4JLVDf7S7XzslgWOhw==", + "requires": { + "caniuse-lite": "^1.0.30001125", + "electron-to-chromium": "^1.3.564", + "escalade": "^3.0.2", + "node-releases": "^1.1.61" + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "node-releases": { + "version": "1.1.77", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.77.tgz", + "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==" + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "react-docgen": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-5.4.3.tgz", + "integrity": "sha512-xlLJyOlnfr8lLEEeaDZ+X2J/KJoe6Nr9AzxnkdQWush5hz2ZSu66w6iLMOScMmxoSHWpWMn+k3v5ZiyCfcWsOA==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@babel/generator": "^7.12.11", + "@babel/runtime": "^7.7.6", + "ast-types": "^0.14.2", + "commander": "^2.19.0", + "doctrine": "^3.0.0", + "estree-to-babel": "^3.1.0", + "neo-async": "^2.6.1", + "node-dir": "^0.1.10", + "strip-indent": "^3.0.0" + } + }, + "react-docgen-typescript": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz", + "integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==", + "dev": true + }, + "react-docgen-typescript-plugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.1.tgz", + "integrity": "sha512-ifcKA71E1W+OdsQ6Z7EwJhGtBIbVHemivFyySAYMEbLzcMw4rDA8QHNoYOI++Hq1Ai8GzSeYtz+UXpmB3H8ZMQ==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "endent": "^2.0.1", + "find-cache-dir": "^3.3.1", + "flat-cache": "^3.0.4", + "micromatch": "^4.0.2", + "react-docgen-typescript": "^1.22.0", + "tslib": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "react-docgen-typescript": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-1.22.0.tgz", + "integrity": "sha512-MPLbF8vzRwAG3GcjdL+OHQlhgtWsLTXs+7uJiHfEeT3Ur7IsZaNYqRTLQ9sj2nB6M6jylcPCeCmH7qbszJmecg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, + "webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "dev": true, + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-element-to-jsx-string": { + "version": "14.3.4", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz", + "integrity": "sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg==", + "dev": true, + "requires": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "17.0.2" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, + "react-emojione": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-emojione/-/react-emojione-5.0.1.tgz", + "integrity": "sha512-sjI6k8uQ14rWENYoAb+2BFQGLBt/cpLDJJNhnZvdFJytAJijhv+JmbmyyrfQPdyID0Cs4N8XFqnek0xq6POwGA==" + }, + "react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" + }, + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + }, + "react-fastclick": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-fastclick/-/react-fastclick-3.0.2.tgz", + "integrity": "sha512-ia0v5WamwSHmGsWaeKVvR79ubjpa5gIxm+ZFqzSbKrZrUfF4t3PF1+cvQzfbSe51muO7VwUHLBW4uu+oGIwEow==" + }, + "react-feather": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/react-feather/-/react-feather-2.0.10.tgz", + "integrity": "sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==", + "requires": { + "prop-types": "^15.7.2" + } + }, + "react-google-login": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/react-google-login/-/react-google-login-5.2.2.tgz", + "integrity": "sha512-JUngfvaSMcOuV0lFff7+SzJ2qviuNMQdqlsDJkUM145xkGPVIfqWXq9Ui+2Dr6jdJWH5KYdynz9+4CzKjI5u6g==", + "requires": { + "@types/react": "*", + "prop-types": "^15.6.0" + } + }, + "react-highlight-words": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-highlight-words/-/react-highlight-words-0.18.0.tgz", + "integrity": "sha512-5z+46eLPjB4JWgOhuQ0E+6iUPTD1U3amiy5KKjzZmeJ5zyvHr91hnzBT3UHya/KlySm5KRTKpYpba9vs67oO2A==", + "requires": { + "highlight-words-core": "^1.2.0", + "memoize-one": "^4.0.0", + "prop-types": "^15.5.8" + }, + "dependencies": { + "memoize-one": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz", + "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw==" + } + } + }, + "react-i18next": { + "version": "11.18.5", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-11.18.5.tgz", + "integrity": "sha512-cKcyuuzIv0YUZ4l9WORflVNuhISPAqQShOAsxwFyYuJoCA7HlLmHm7XnvO6hfAGmGpDNRhJHoBX8hG49Cb2xZQ==", + "requires": { + "@babel/runtime": "^7.14.5", + "html-parse-stringify": "^3.0.1" + } + }, + "react-inspector": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", + "integrity": "sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "is-dom": "^1.0.0", + "prop-types": "^15.0.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-merge-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz", + "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==", + "dev": true + }, + "react-moment": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/react-moment/-/react-moment-0.9.7.tgz", + "integrity": "sha512-ifzUrUGF6KRsUN2pRG5k56kO0mJBr8kRkWb0wNvtFIsBIxOuPxhUpL1YlXwpbQCbHq23hUu6A0VEk64HsFxk9g==" + }, + "react-motion": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/react-motion/-/react-motion-0.5.2.tgz", + "integrity": "sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==", + "requires": { + "performance-now": "^0.2.0", + "prop-types": "^15.5.8", + "raf": "^3.1.0" + }, + "dependencies": { + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha512-YHk5ez1hmMR5LOkb9iJkLKqoBlL7WD5M8ljC75ZfzXriuBIVNuecaXuU7e+hOwyqf24Wxhh7Vxgt7Hnw9288Tg==" + } + } + }, + "react-outside-click-handler": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-outside-click-handler/-/react-outside-click-handler-1.3.0.tgz", + "integrity": "sha512-Te/7zFU0oHpAnctl//pP3hEAeobfeHMyygHB8MnjP6sX5OR8KHT1G3jmLsV3U9RnIYo+Yn+peJYWu+D5tUS8qQ==", + "requires": { + "airbnb-prop-types": "^2.15.0", + "consolidated-events": "^1.1.1 || ^2.0.0", + "document.contains": "^1.0.1", + "object.values": "^1.1.0", + "prop-types": "^15.7.2" + } + }, + "react-perfect-scrollbar": { + "version": "1.5.8", + "resolved": "https://registry.npmjs.org/react-perfect-scrollbar/-/react-perfect-scrollbar-1.5.8.tgz", + "integrity": "sha512-bQ46m70gp/HJtiBOF3gRzBISSZn8FFGNxznTdmTG8AAwpxG1bJCyn7shrgjEvGSQ5FJEafVEiosY+ccER11OSA==", + "requires": { + "perfect-scrollbar": "^1.5.0", + "prop-types": "^15.6.1" + } + }, + "react-player": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/react-player/-/react-player-2.10.1.tgz", + "integrity": "sha512-ova0jY1Y1lqLYxOehkzbNEju4rFXYVkr5rdGD71nsiG4UKPzRXQPTd3xjoDssheoMNjZ51mjT5ysTrdQ2tEvsg==", + "requires": { + "deepmerge": "^4.0.0", + "load-script": "^1.0.0", + "memoize-one": "^5.1.1", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.0.1" + }, + "dependencies": { + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + } + } + }, + "react-redux": { + "version": "7.2.8", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz", + "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + } + } + }, + "react-refresh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", + "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==" + }, + "react-router": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.3.tgz", + "integrity": "sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "mini-create-react-context": "^0.4.0", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng==", + "requires": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.3", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + } + }, + "react-scripts": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", + "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", + "requires": { + "@babel/core": "^7.16.0", + "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", + "@svgr/webpack": "^5.5.0", + "babel-jest": "^27.4.2", + "babel-loader": "^8.2.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "bfj": "^7.0.2", + "browserslist": "^4.18.1", + "camelcase": "^6.2.1", + "case-sensitive-paths-webpack-plugin": "^2.4.0", + "css-loader": "^6.5.1", + "css-minimizer-webpack-plugin": "^3.2.0", + "dotenv": "^10.0.0", + "dotenv-expand": "^5.1.0", + "eslint": "^8.3.0", + "eslint-config-react-app": "^7.0.1", + "eslint-webpack-plugin": "^3.1.1", + "file-loader": "^6.2.0", + "fs-extra": "^10.0.0", + "fsevents": "^2.3.2", + "html-webpack-plugin": "^5.5.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^27.4.3", + "jest-resolve": "^27.4.2", + "jest-watch-typeahead": "^1.0.0", + "mini-css-extract-plugin": "^2.4.5", + "postcss": "^8.4.4", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^6.2.1", + "postcss-normalize": "^10.0.1", + "postcss-preset-env": "^7.0.1", + "prompts": "^2.4.2", + "react-app-polyfill": "^3.0.0", + "react-dev-utils": "^12.0.1", + "react-refresh": "^0.11.0", + "resolve": "^1.20.0", + "resolve-url-loader": "^4.0.0", + "sass-loader": "^12.3.0", + "semver": "^7.3.5", + "source-map-loader": "^3.0.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.2", + "terser-webpack-plugin": "^5.2.5", + "webpack": "^5.64.4", + "webpack-dev-server": "^4.6.0", + "webpack-manifest-plugin": "^4.0.2", + "workbox-webpack-plugin": "^6.4.1" + }, + "dependencies": { + "@babel/plugin-proposal-decorators": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.10.tgz", + "integrity": "sha512-wdGTwWF5QtpTY/gbBtQLAiCnoxfD4qMbN87NYZle1dOZ9Os8Y6zXcKrIaOU8W+TIvFUWVGG9tUgNww3CjXRVVw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/plugin-syntax-decorators": "^7.18.6" + } + }, + "@babel/plugin-transform-flow-strip-types": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.18.9.tgz", + "integrity": "sha512-+G6rp2zRuOAInY5wcggsx4+QVao1qPM0osC9fTUVlAV3zOrzTCnrMAFVnR6+a3T8wz1wFIH7KhYMcMB3u1n80A==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-flow": "^7.18.6" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", + "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "@babel/preset-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", + "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-transform-typescript": "^7.18.6" + } + }, + "@jest/console": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", + "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^28.1.3", + "jest-util": "^28.1.3", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz", + "integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + } + } + }, + "@jest/test-result": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", + "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", + "requires": { + "@jest/console": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz", + "integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@svgr/babel-plugin-add-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==" + }, + "@svgr/babel-plugin-remove-jsx-attribute": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", + "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==" + }, + "@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", + "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==" + }, + "@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", + "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==" + }, + "@svgr/babel-plugin-svg-dynamic-title": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", + "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==" + }, + "@svgr/babel-plugin-svg-em-dimensions": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", + "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==" + }, + "@svgr/babel-plugin-transform-react-native-svg": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", + "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==" + }, + "@svgr/babel-plugin-transform-svg-component": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", + "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==" + }, + "@svgr/babel-preset": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", + "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", + "requires": { + "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", + "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", + "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", + "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", + "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", + "@svgr/babel-plugin-transform-svg-component": "^5.5.0" + } + }, + "@svgr/core": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", + "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", + "requires": { + "@svgr/plugin-jsx": "^5.5.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^7.0.0" + } + }, + "@svgr/hast-util-to-babel-ast": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", + "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", + "requires": { + "@babel/types": "^7.12.6" + } + }, + "@svgr/plugin-jsx": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", + "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", + "requires": { + "@babel/core": "^7.12.3", + "@svgr/babel-preset": "^5.5.0", + "@svgr/hast-util-to-babel-ast": "^5.5.0", + "svg-parser": "^2.0.2" + } + }, + "@svgr/plugin-svgo": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", + "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", + "requires": { + "cosmiconfig": "^7.0.0", + "deepmerge": "^4.2.2", + "svgo": "^1.2.2" + } + }, + "@svgr/webpack": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", + "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/plugin-transform-react-constant-elements": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-react": "^7.12.5", + "@svgr/core": "^5.5.0", + "@svgr/plugin-jsx": "^5.5.0", + "@svgr/plugin-svgo": "^5.5.0", + "loader-utils": "^2.0.0" + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "autoprefixer": { + "version": "10.4.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz", + "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==", + "requires": { + "browserslist": "^4.21.3", + "caniuse-lite": "^1.0.30001373", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-preset-react-app": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz", + "integrity": "sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-class-properties": "^7.16.0", + "@babel/plugin-proposal-decorators": "^7.16.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", + "@babel/plugin-proposal-numeric-separator": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.0", + "@babel/plugin-proposal-private-methods": "^7.16.0", + "@babel/plugin-transform-flow-strip-types": "^7.16.0", + "@babel/plugin-transform-react-display-name": "^7.16.0", + "@babel/plugin-transform-runtime": "^7.16.4", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@babel/preset-typescript": "^7.16.0", + "@babel/runtime": "^7.16.3", + "babel-plugin-macros": "^3.1.0", + "babel-plugin-transform-react-remove-prop-types": "^0.4.24" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==" + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz", + "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==" + }, + "clean-css": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", + "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "requires": { + "source-map": "~0.6.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + }, + "core-js": { + "version": "3.25.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.25.0.tgz", + "integrity": "sha512-CVU1xvJEfJGhyCpBrzzzU1kjCfgsGUxhEvwUV2e/cOedYWHdmluamx+knDnmhqALddMG16fZvIqvs9aijsHHaA==" + }, + "css-blank-pseudo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", + "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-has-pseudo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", + "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + } + }, + "css-prefers-color-scheme": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", + "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==" + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "cssdb": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.1.tgz", + "integrity": "sha512-pT3nzyGM78poCKLAEy2zWIVX2hikq6dIrjuZzLV98MumBg+xMTNYfHx7paUlfiRTgg91O/vR889CIf+qiv79Rw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" + }, + "emittery": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", + "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "eslint-config-react-app": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", + "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", + "requires": { + "@babel/core": "^7.16.0", + "@babel/eslint-parser": "^7.16.3", + "@rushstack/eslint-patch": "^1.1.0", + "@typescript-eslint/eslint-plugin": "^5.5.0", + "@typescript-eslint/parser": "^5.5.0", + "babel-preset-react-app": "^10.0.1", + "confusing-browser-globals": "^1.0.11", + "eslint-plugin-flowtype": "^8.0.3", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jest": "^25.3.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.27.1", + "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-testing-library": "^5.0.1" + } + }, + "eslint-plugin-flowtype": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", + "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", + "requires": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + } + }, + "eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz", + "integrity": "sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==", + "requires": { + "@babel/runtime": "^7.18.9", + "aria-query": "^4.2.2", + "array-includes": "^3.1.5", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.4.3", + "axobject-query": "^2.2.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.2", + "language-tags": "^1.0.5", + "minimatch": "^3.1.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==" + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz", + "integrity": "sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==", + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "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-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + } + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "requires": { + "duplexer": "^0.1.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==" + }, + "immer": { + "version": "9.0.15", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", + "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==" + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-message-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", + "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^28.1.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^28.1.3", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz", + "integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==", + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==" + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-watch-typeahead": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", + "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", + "requires": { + "ansi-escapes": "^4.3.1", + "chalk": "^4.0.0", + "jest-regex-util": "^28.0.0", + "jest-watcher": "^28.0.0", + "slash": "^4.0.0", + "string-length": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "jest-regex-util": { + "version": "28.0.2", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", + "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==" + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==" + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "jest-watcher": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", + "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", + "requires": { + "@jest/test-result": "^28.1.3", + "@jest/types": "^28.1.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.10.2", + "jest-util": "^28.1.3", + "string-length": "^4.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", + "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", + "requires": { + "@jest/schemas": "^28.1.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "17.0.11", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.11.tgz", + "integrity": "sha512-aB4y9UDUXTSMxmM4MH+YnuR0g5Cph3FLQBoWoMB21DSvFVAxRVEHEMx3TLh+zUZYMCQtKiqazz0Q4Rre31f/OA==", + "requires": { + "@types/yargs-parser": "*" + } + }, + "jest-util": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", + "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", + "requires": { + "@jest/types": "^28.1.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + } + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "mini-css-extract-plugin": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", + "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", + "requires": { + "schema-utils": "^4.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "postcss-attribute-case-insensitive": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", + "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-browser-comments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", + "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==" + }, + "postcss-color-functional-notation": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", + "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-hex-alpha": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", + "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-rebeccapurple": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", + "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", + "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-properties": { + "version": "12.1.8", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.8.tgz", + "integrity": "sha512-8rbj8kVu00RQh2fQF81oBqtduiANu4MIxhyf0HbbStgPtnFlWn0yiaYTpLHrPnJbffVY1s9apWsIoVZcc68FxA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-selectors": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", + "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-dir-pseudo-class": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", + "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-double-position-gradients": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", + "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-env-function": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", + "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-flexbugs-fixes": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", + "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==" + }, + "postcss-focus-visible": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", + "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-focus-within": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", + "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", + "requires": { + "postcss-selector-parser": "^6.0.9" + } + }, + "postcss-font-variant": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", + "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==" + }, + "postcss-gap-properties": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", + "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==" + }, + "postcss-image-set-function": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", + "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-initial": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", + "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==" + }, + "postcss-lab-function": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", + "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", + "requires": { + "@csstools/postcss-progressive-custom-properties": "^1.1.0", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + } + }, + "postcss-logical": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", + "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==" + }, + "postcss-media-minmax": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", + "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==" + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==" + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nesting": { + "version": "10.1.10", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.1.10.tgz", + "integrity": "sha512-lqd7LXCq0gWc0wKXtoKDru5wEUNjm3OryLVNRZ8OnW8km6fSNUuFrjEhU3nklxXE2jvd4qrox566acgh+xQt8w==", + "requires": { + "@csstools/selector-specificity": "^2.0.0", + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-normalize": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", + "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", + "requires": { + "@csstools/normalize.css": "*", + "postcss-browser-comments": "^4", + "sanitize.css": "*" + } + }, + "postcss-overflow-shorthand": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", + "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-page-break": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", + "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==" + }, + "postcss-place": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", + "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-preset-env": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.0.tgz", + "integrity": "sha512-leqiqLOellpLKfbHkD06E04P6d9ZQ24mat6hu4NSqun7WG0UhspHR5Myiv/510qouCjoo4+YJtNOqg5xHaFnCA==", + "requires": { + "@csstools/postcss-cascade-layers": "^1.0.5", + "@csstools/postcss-color-function": "^1.1.1", + "@csstools/postcss-font-format-keywords": "^1.0.1", + "@csstools/postcss-hwb-function": "^1.0.2", + "@csstools/postcss-ic-unit": "^1.0.1", + "@csstools/postcss-is-pseudo-class": "^2.0.7", + "@csstools/postcss-nested-calc": "^1.0.0", + "@csstools/postcss-normalize-display-values": "^1.0.1", + "@csstools/postcss-oklab-function": "^1.1.1", + "@csstools/postcss-progressive-custom-properties": "^1.3.0", + "@csstools/postcss-stepped-value-functions": "^1.0.1", + "@csstools/postcss-text-decoration-shorthand": "^1.0.0", + "@csstools/postcss-trigonometric-functions": "^1.0.2", + "@csstools/postcss-unset-value": "^1.0.2", + "autoprefixer": "^10.4.8", + "browserslist": "^4.21.3", + "css-blank-pseudo": "^3.0.3", + "css-has-pseudo": "^3.0.4", + "css-prefers-color-scheme": "^6.0.3", + "cssdb": "^7.0.0", + "postcss-attribute-case-insensitive": "^5.0.2", + "postcss-clamp": "^4.1.0", + "postcss-color-functional-notation": "^4.2.4", + "postcss-color-hex-alpha": "^8.0.4", + "postcss-color-rebeccapurple": "^7.1.1", + "postcss-custom-media": "^8.0.2", + "postcss-custom-properties": "^12.1.8", + "postcss-custom-selectors": "^6.0.3", + "postcss-dir-pseudo-class": "^6.0.5", + "postcss-double-position-gradients": "^3.1.2", + "postcss-env-function": "^4.0.6", + "postcss-focus-visible": "^6.0.4", + "postcss-focus-within": "^5.0.4", + "postcss-font-variant": "^5.0.0", + "postcss-gap-properties": "^3.0.5", + "postcss-image-set-function": "^4.0.7", + "postcss-initial": "^4.0.1", + "postcss-lab-function": "^4.2.1", + "postcss-logical": "^5.0.4", + "postcss-media-minmax": "^5.0.0", + "postcss-nesting": "^10.1.10", + "postcss-opacity-percentage": "^1.1.2", + "postcss-overflow-shorthand": "^3.0.4", + "postcss-page-break": "^3.0.4", + "postcss-place": "^7.0.5", + "postcss-pseudo-class-any-link": "^7.1.6", + "postcss-replace-overflow-wrap": "^4.0.0", + "postcss-selector-not": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-pseudo-class-any-link": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", + "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-replace-overflow-wrap": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", + "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==" + }, + "postcss-selector-not": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", + "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "pretty-format": { + "version": "28.1.3", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", + "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", + "requires": { + "@jest/schemas": "^28.1.3", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + } + } + }, + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "requires": { + "asap": "~2.0.6" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "react-app-polyfill": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", + "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", + "requires": { + "core-js": "^3.19.2", + "object-assign": "^4.1.1", + "promise": "^8.1.0", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.9", + "whatwg-fetch": "^3.6.2" + } + }, + "react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "requires": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "loader-utils": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", + "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==" + } + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + } + } + }, + "sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "requires": { + "escape-string-regexp": "^2.0.0" + } + }, + "string-length": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", + "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", + "requires": { + "char-regex": "^2.0.0", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" + }, + "char-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.1.tgz", + "integrity": "sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==" + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "workbox-webpack-plugin": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.4.tgz", + "integrity": "sha512-LmWm/zoaahe0EGmMTrSLUi+BjyR3cdGEfU3fS6PN1zKFYbqAKuQ+Oy/27e4VSXsyIwAw8+QDfk1XHNGtZu9nQg==", + "requires": { + "fast-json-stable-stringify": "^2.1.0", + "pretty-bytes": "^5.4.1", + "upath": "^1.2.0", + "webpack-sources": "^1.4.3", + "workbox-build": "6.5.4" + } + } + } + }, + "react-scrollbar": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/react-scrollbar/-/react-scrollbar-0.5.6.tgz", + "integrity": "sha512-TsSLsuovOlxmfTxY9bRjRUfQjycvfs73L4gz7yE+2D8Qs7U3zhwbGS0lj0JScCDipcyn7EX66LsaI00cU3aRSQ==", + "requires": { + "config": "^1.24.0", + "line-height": "^0.1.1", + "react-motion": "^0.5.2" + } + }, + "react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "requires": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + } + }, + "react-shortcuts": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-shortcuts/-/react-shortcuts-2.1.0.tgz", + "integrity": "sha512-yETQgoy/KRCOPjdlGSnfTjyVHwJYsFoHtVmuLzJABYBAnilpm1M14DhDavuAAMElbaQlXunOwKjh0Oq3I6Vt0A==", + "requires": { + "combokeys": "^3.0.1", + "events": "^1.0.2", + "invariant": "^2.1.0", + "just-reduce-object": "^1.0.3", + "platform": "^1.3.0", + "prop-types": "^15.5.8" + }, + "dependencies": { + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==" + } + } + }, + "react-showdown": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/react-showdown/-/react-showdown-2.3.1.tgz", + "integrity": "sha512-3O9Gz6HF1MQbGK17gYOO6EJP27h9Sp+g/L7KeOhMJERuutYP3802MPaL8JybjeI97X9HTeeN4A89WjOpEHl3NQ==", + "requires": { + "domhandler": "^4.0.0", + "htmlparser2": "^6.0.1", + "showdown": "^1.9.1" + }, + "dependencies": { + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + } + } + }, + "react-sidebar": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-sidebar/-/react-sidebar-3.0.2.tgz", + "integrity": "sha512-LG/JO1cJvdRqSmUT+DOhJrml/b45/UqM9nm8emcgbJb5EKNegKCObZcrRqyzVix42VfFf0odytviAAFEYYTu1Q==", + "requires": { + "@babel/runtime": ">=7.0.0-beta.56", + "prop-types": "^15.6.2" + } + }, + "react-sortable-hoc": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-1.11.0.tgz", + "integrity": "sha512-v1CDCvdfoR3zLGNp6qsBa4J1BWMEVH25+UKxF/RvQRh+mrB+emqtVHMgZ+WreUiKJoEaiwYoScaueIKhMVBHUg==", + "requires": { + "@babel/runtime": "^7.2.0", + "invariant": "^2.2.4", + "prop-types": "^15.5.7" + } + }, + "react-svg": { + "version": "11.2.5", + "resolved": "https://registry.npmjs.org/react-svg/-/react-svg-11.2.5.tgz", + "integrity": "sha512-uUMhRVdU//5qktiTSO2W6nQeHRLwYA1FsWANQFB5O33UgT2uT0V5wVapu46+wz1mx6wt1j53+1aA8QuNn4lJ6A==", + "requires": { + "@babel/runtime": "^7.12.13", + "@tanem/svg-injector": "^8.2.4", + "prop-types": "^15.7.2" + } + }, + "react-swipeable": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/react-swipeable/-/react-swipeable-5.5.1.tgz", + "integrity": "sha512-EQObuU3Qg3JdX3WxOn5reZvOSCpU4fwpUAs+NlXSN3y+qtsO2r8VGkVnOQzmByt3BSYj9EWYdUOUfi7vaMdZZw==", + "requires": { + "prop-types": "^15.6.2" + } + }, + "react-test-renderer": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", + "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", + "requires": { + "object-assign": "^4.1.1", + "react-is": "^17.0.2", + "react-shallow-renderer": "^16.13.1", + "scheduler": "^0.20.2" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } + } + }, + "react-textarea-autosize": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz", + "integrity": "sha512-CdtmP8Dc19xL8/R6sWvtknD/eCXkQr30dtvC4VmGInhRsfF8X/ihXCq6+9l9qbxmKRiq407/7z5fxE7cVWQNgQ==", + "requires": { + "@babel/runtime": "^7.10.2", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + } + }, + "react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, + "react-virtualized": { + "version": "9.22.3", + "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz", + "integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==", + "requires": { + "@babel/runtime": "^7.7.2", + "clsx": "^1.0.4", + "dom-helpers": "^5.1.3", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.4" + } + }, + "react-virtuoso": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-2.10.2.tgz", + "integrity": "sha512-nQ8Wt/q64q6walcXo4y9SXkvZqjwuLiNUv7aKW3poKoZno8agTgeqcX1GMq3GPlaJ8wR5XMGwBxX4HONBMAGfg==", + "requires": { + "@virtuoso.dev/react-urx": "^0.2.12", + "@virtuoso.dev/urx": "^0.2.12" + } + }, + "react-zoom-pan-pinch": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/react-zoom-pan-pinch/-/react-zoom-pan-pinch-2.1.3.tgz", + "integrity": "sha512-a5AChOWhjo0RmxsNZXGQIlNh3e3nLU6m4V6M+6dlbPNk5d+MtMxgKWyA5zpR06Lp3OZkZVF9nR8JeWSvKwck9g==" + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "requires": { + "pify": "^2.3.0" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + } + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "requires": { + "p-limit": "^1.1.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "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" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "requires": { + "util.promisify": "^1.0.0" + } + }, + "recast": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.19.1.tgz", + "integrity": "sha512-8FCjrBxjeEU2O6I+2hyHyBFH1siJbMBLwIRvVr1T3FD2cL754sOaJDsJ/8h3xYltasbJ8jqWRIhMuDGBSiSbjw==", + "dev": true, + "requires": { + "ast-types": "0.13.3", + "esprima": "~4.0.0", + "private": "^0.1.8", + "source-map": "~0.6.1" + }, + "dependencies": { + "ast-types": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz", + "integrity": "sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "recoil": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/recoil/-/recoil-0.4.1.tgz", + "integrity": "sha512-vp6KPwlHOjJ4bJofmdDchmgI9ilMTCoUisK8/WYLl8dThH7e7KmtZttiLgvDb2Em99dUfTEsk8vT8L1nUMgqXQ==", + "requires": { + "hamt_plus": "1.0.2" + } + }, + "recursive-readdir": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", + "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "requires": { + "minimatch": "3.0.4" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "redux": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", + "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha512-qOLsBKHCpSOFKK1NUOCGC5VyeufB6lEsFe92AL2bhIJsacZS1qdoOZSbPk3MYKuT2cFlRDnulKXuuElIrMjGUg==" + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "optional": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==" + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + }, + "regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "registry-auth-token": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", + "integrity": "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg==", + "dev": true, + "requires": { + "rc": "1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==" + }, + "remark-external-links": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", + "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "is-absolute-url": "^3.0.0", + "mdast-util-definitions": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + } + } + }, + "remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "dev": true + }, + "remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "dev": true, + "requires": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "dev": true, + "requires": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + } + }, + "remark-slug": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", + "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "dev": true, + "requires": { + "mdast-squeeze-paragraphs": "^4.0.0" + } + }, + "remarkable": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remarkable/-/remarkable-2.0.1.tgz", + "integrity": "sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA==", + "requires": { + "argparse": "^1.0.10", + "autolinker": "^3.11.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==" + }, + "renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "requires": { + "boolbase": "^1.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==", + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + } + } + }, + "request-promise-core": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", + "requires": { + "lodash": "^4.17.19" + } + }, + "request-promise-native": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", + "requires": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, + "resolve": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", + "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", + "requires": { + "is-core-module": "^2.1.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + } + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" + }, + "resolve-url-loader": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.2.tgz", + "integrity": "sha512-QEb4A76c8Mi7I3xNKXlRKQSlLBwjUV/ULFMP+G7n3/7tJZ8MG5wsZ3ucxP1Jz8Vevn6fnJsxDx9cIls+utGzPQ==", + "requires": { + "adjust-sourcemap-loader": "3.0.0", + "camelcase": "5.3.1", + "compose-function": "3.0.3", + "convert-source-map": "1.7.0", + "es6-iterator": "2.0.3", + "loader-utils": "1.2.3", + "postcss": "7.0.21", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.6.1" + }, + "dependencies": { + "adjust-sourcemap-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-3.0.0.tgz", + "integrity": "sha512-YBrGyT2/uVQ/c6Rr+t6ZJXniY03YtHGMJQYal368burRGYKqhx9qGTWqcBU5s1CwYY9E/ri63RYyG1IacMZtqw==", + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", + "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "postcss": { + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha512-eEjL8FdkdsxApd0yWVZgBGzfCQiT8yqSc2H1p4jpZpQdtz7ohETiDMoje5PlM8I9WgkqkreVxFUKYOiJdVWDXw==", + "requires": { + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha512-+4nRk0k3oEpwUB7/CalD7xE2z4VmtEnnq0GO2IPTkrooTrAhEsWvuLF5iWP1dXrwluki/azwXV1ve7gtYuPldg==" + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha512-W6V2fix7nCLUYX1v6eGPrBOZlc03/faqzP4sUxMAJMBMOPYhfV/RyLegTufn5gJKaOITyi+gvf0LXDZ9NzkHnQ==" + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==" + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "2.78.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", + "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + } + } + }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==", + "requires": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==" + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", + "dev": true, + "requires": { + "aproba": "^1.1.1" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + } + } + }, + "rxjs": { + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz", + "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==", + "requires": { + "tslib": "^2.1.0" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "sanitize.css": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz", + "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==" + }, + "sass": { + "version": "1.54.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.5.tgz", + "integrity": "sha512-p7DTOzxkUPa/63FU0R3KApkRHwcVZYC0PLnLm5iyZACyp15qSi32x7zVUhRdABAATmkALqgGrjCJAcWvobmhHw==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "dependencies": { + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + } + } + }, + "sass-loader": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", + "requires": { + "clone-deep": "^4.0.1", + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "requires": { + "kind-of": "^6.0.2" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "saxes": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.11.tgz", + "integrity": "sha512-Ydydq3zC+WYDJK1+gRxRapLIED9PWeSuuS41wqyoRmzvhhh9nc+QQrVMKJYzJFULazeGhzSV0QleN2wD3boh2g==", + "requires": { + "xmlchars": "^2.1.1" + } + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "scroll-into-view-if-needed": { + "version": "2.2.29", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz", + "integrity": "sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==", + "requires": { + "compute-scroll-into-view": "^1.0.17" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" + }, + "selfsigned": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", + "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", + "requires": { + "node-forge": "^1" + } + }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha512-FMW2RvqNr03x+C0WxTyu6sOv21oOjkq5j8tjquWccwa6ScNyGFOGJVpuS1NmTVGBAHS07xnSKotgf2ehQmf9iA==", + "dev": true, + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==" + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha512-J1zdXCky5GmNnuauESROVu31MQSnLoYvlyEn6j2Ztk6Q5EHFIhxkMhYcv6vuDzl2XEzoRr856QwzMgWM/TmZgw==", + "requires": { + "is-extendable": "^0.1.1", + "kind-of": "^2.0.1", + "lazy-cache": "^0.2.3", + "mixin-object": "^2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha512-0u8i1NZ/mg0b+W3MGGw5I7+6Eib2nx72S/QvXa0hYjEkjTknYmEYQJwGu3mLC0BrhtJjtQafTkyRUQ75Kx0LVg==", + "requires": { + "is-buffer": "^1.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha512-gkX52wvU/R8DVMMt78ATVPFMJqfW8FPz1GZ1sVHBVQHmu/WvhIWE4cE1GBzhJNFicDeYhnwp6Rl35BcAIM3YOQ==" + } + } + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" + }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "dependencies": { + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + } + } + }, + "short-uuid": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/short-uuid/-/short-uuid-4.2.0.tgz", + "integrity": "sha512-r3cxuPPZSuF0QkKsK9bBR7u+7cwuCRzWzgjPh07F5N2iIUNgblnMHepBY16xgj5t1lG9iOP9k/TEafY1qhRzaw==", + "requires": { + "any-base": "^1.1.0", + "uuid": "^8.3.2" + } + }, + "shortcuts": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shortcuts/-/shortcuts-1.8.1.tgz", + "integrity": "sha512-2AURf/O3BbPHuzLtnnzrF/mXut8xZy3oneFTGjvXPQn1+apw1cBpy1+493NEKab+yO8ND3rbCdD7uVK+J2C93A==" + }, + "showdown": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/showdown/-/showdown-1.9.1.tgz", + "integrity": "sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA==", + "requires": { + "yargs": "^14.2" + }, + "dependencies": { + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==" + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "yargs": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", + "requires": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "yargs-parser": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", + "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + } + }, + "socket.io-client": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.5.0.tgz", + "integrity": "sha512-lOO9clmdgssDykiOmVQQitwBAF3I6mYcQAo7hQ7AM6Ny5X7fp8hIJ3HcQs3Rjz4SoggoxA1OgrQyY8EgTbcPYw==", + "requires": { + "backo2": "1.0.2", + "component-bind": "1.0.0", + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "engine.io-client": "~3.5.0", + "has-binary2": "~1.0.2", + "indexof": "0.0.1", + "parseqs": "0.0.6", + "parseuri": "0.0.6", + "socket.io-parser": "~3.3.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "socket.io-parser": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", + "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", + "requires": { + "component-emitter": "~1.3.0", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha512-c2cu3UxbI+b6kR3fy0nRnAhodsvR9dx7U5+znCOzdj6IfP3upFURTr0Xl5BlQZNKZjEtxrmVyfSdeE3O57smoQ==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "requires": { + "is-plain-obj": "^1.0.0" + }, + "dependencies": { + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" + } + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.1.tgz", + "integrity": "sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA==", + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.1" + } + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "^0.5.6" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true + }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", + "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==" + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "splaytree": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/splaytree/-/splaytree-3.1.1.tgz", + "integrity": "sha512-9FaQ18FF0+sZc/ieEeXHt+Jw2eSpUgUtTLDYB/HXKWvhYVyOc7h1hzkn5MMO3GPib9MmXG1go8+OsBBzs/NMww==" + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==" + }, + "stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + } + } + }, + "stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==" + }, + "store2": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.14.2.tgz", + "integrity": "sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==", + "dev": true + }, + "storybook-dark-mode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-1.1.0.tgz", + "integrity": "sha512-F+hG02zYGBzxGTUonA1XDV/CtMYm3OjF38Tu1CIUN+w+8hwUrwLcOtgtLLw6VjSrZdJ/ECK+tjXdKTV4oZqAXw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.0.0", + "memoizerific": "^1.11.3" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } + } + }, + "storybook-preset-craco": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/storybook-preset-craco/-/storybook-preset-craco-0.0.6.tgz", + "integrity": "sha512-1HwDzjVDcUi7hJJvj4mYRbabvF1MGFgpnph9wQml8j9yamgLm2ISA9vaFMskWGNId9vyfPivINcEhcTNdmPhBA==", + "dev": true, + "requires": { + "@storybook/preset-create-react-app": "^3.1.5" + }, + "dependencies": { + "@pmmmwh/react-refresh-webpack-plugin": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz", + "integrity": "sha512-br5Qwvh8D2OQqSXpd1g/xqXKnK0r+Jz6qVKBbWmpUcrbGOxUrf39V5oZ1876084CGn18uMdR5uvPqBv9UqtBjQ==", + "dev": true, + "requires": { + "ansi-html": "^0.0.7", + "error-stack-parser": "^2.0.6", + "html-entities": "^1.2.1", + "native-url": "^0.2.6", + "schema-utils": "^2.6.5", + "source-map": "^0.7.3" + } + }, + "@storybook/preset-create-react-app": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@storybook/preset-create-react-app/-/preset-create-react-app-3.2.0.tgz", + "integrity": "sha512-lLoWCGr5cV+JNDRKYHC2gD+P2eyBqdN8qhmBa+PxDgPSNKfgUf9Wnoh+C7WTG5q2DEeR9SvUpQpZomX9DDQa4Q==", + "dev": true, + "requires": { + "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", + "@types/babel__core": "^7.1.7", + "@types/webpack": "^4.41.13", + "babel-plugin-react-docgen": "^4.1.0", + "pnp-webpack-plugin": "^1.6.4", + "react-docgen-typescript-plugin": "^1.0.0", + "semver": "^7.3.5" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha512-JoAxEa1DfP9m2xfB/y2r/aKcwXNlltr4+0QSBC4TrLfcxyvepX2Pv0t/xpgGV5bGsDzCYV8SzjWgyCW0T9yYbA==", + "dev": true + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==" + }, + "string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "string.prototype.padstart": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.3.tgz", + "integrity": "sha512-NZydyOMtYxpTjGqp0VN5PYUF/tsU15yDMZnUdj16qRUIUiMJkHHSDElYyQFrMu+/WloTpA7MQSiADhBicDfaoA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "string.prototype.trim": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.6.tgz", + "integrity": "sha512-8lMR2m+U0VJTPp6JjvJTtGyc4FIGq9CdRt7O9p6T0e6K4vjU+OP+SQJpbe/SBmRcCUIvNUnjsbmY6lnMp8MhsQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "dev": true, + "requires": { + "inline-style-parser": "0.1.1" + } + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "symbol.prototype.description": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.5.tgz", + "integrity": "sha512-x738iXRYsrAt9WBhRCVG5BtIC3B7CUkFwbHW2zOvGtwM33s7JjrCDyq8V0zgMYVb5ymsL8+qkzzpANH63CPQaQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-symbol-description": "^1.0.0", + "has-symbols": "^1.0.2", + "object.getownpropertydescriptors": "^2.1.2" + } + }, + "synchronous-promise": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.16.tgz", + "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", + "dev": true + }, + "synthetic-dom": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/synthetic-dom/-/synthetic-dom-1.4.0.tgz", + "integrity": "sha512-mHv51ZsmZ+ShT/4s5kg+MGUIhY7Ltq4v03xpN1c8T1Krb5pScsh/lzEjyhrVD0soVDbThbd2e+4dD9vnDG4rhg==" + }, + "tailwindcss": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz", + "integrity": "sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==", + "requires": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "dependencies": { + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" + }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "telejson": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-6.0.8.tgz", + "integrity": "sha512-nerNXi+j8NK1QEfBHtZUN/aLdDcyupA//9kAboYLrtzZlPLpUfqbVGWb9zz91f/mIjRbAYhbgtnJHY8I1b5MBg==", + "dev": true, + "requires": { + "@types/is-function": "^1.0.0", + "global": "^4.4.0", + "is-function": "^1.0.2", + "is-regex": "^1.1.2", + "is-symbol": "^1.0.3", + "isobject": "^4.0.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3" + }, + "dependencies": { + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + } + } + }, + "temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "dev": true, + "requires": { + "rimraf": "~2.6.2" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "dependencies": { + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + } + } + }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-3.1.0.tgz", + "integrity": "sha512-cjdZte66fYkZ65rQ2oJfrdCAkkhJA7YLYk5eGOcGCSGlq0ieZupRdjedSQXYknMPo2IveQL+tPdrxUkERENCFA==", + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.2.1", + "p-limit": "^3.0.2", + "schema-utils": "^2.6.6", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.8.0", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "requires": { + "find-up": "^4.0.0" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==" + }, + "tiny-invariant": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", + "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + }, + "tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha512-LhVdShQD/4Mk4zXNroIQZJC+Ap3zgLcDuwEdcmLv9CCO73NWockQDwyUnW/m8VX/EElfL6FcYx7EeutN4HJA6A==" + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "dev": true + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==", + "dev": true, + "optional": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==" + }, + "trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true + }, + "tryer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", + "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" + }, + "ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==" + }, + "tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==" + }, + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==" + }, + "uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==", + "dev": true, + "optional": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", + "dev": true + }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + }, + "unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + } + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==" + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==" + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "dev": true + }, + "unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "dev": true + }, + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true + }, + "unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "dev": true + }, + "unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "dev": true, + "requires": { + "unist-util-is": "^4.0.0" + } + }, + "unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "dev": true, + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "requires": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==" + } + } + }, + "untildify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", + "integrity": "sha512-sJjbDp2GodvkB0FZZcn7k6afVisqX5BZD7Yq3xp4nN2O15BBK0cLm3Vwn2vQaF7UDS0UUsrQMkkplmDI5fskig==", + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + } + } + }, + "url-loader": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.3.0.tgz", + "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==", + "requires": { + "loader-utils": "^1.2.3", + "mime": "^2.4.4", + "schema-utils": "^2.5.0" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==" + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "use-composed-ref": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.3.0.tgz", + "integrity": "sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ==" + }, + "use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" + }, + "use-latest": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.1.tgz", + "integrity": "sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw==", + "requires": { + "use-isomorphic-layout-effect": "^1.1.1" + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==" + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "uuid-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", + "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", + "dev": true + }, + "uuid-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uuid-time/-/uuid-time-1.0.0.tgz", + "integrity": "sha512-F0EzKK+aqt41uDutE+qukIta0CkMJ212qkIWT7uUCy0DjbyMEGpNkiLQfdByBveEt28Z/ywZU7u4CQ/a03oCaA==" + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==" + } + } + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==", + "requires": { + "user-home": "^1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + } + } + }, + "vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + } + } + }, + "vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "dev": true + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==" + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.1.2.tgz", + "integrity": "sha512-p10l/ayESzrBMYWRID6xbuCKh2Fp77+sA0doRuGn4tTIMrrZVeqfpKjXHY+oDh3K4nLdPgNwMTVP6Vp4pvqbNg==", + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + } + } + }, + "wait-for-expect": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/wait-for-expect/-/wait-for-expect-3.0.2.tgz", + "integrity": "sha512-cfS1+DZxuav1aBYbaO/kE06EOS8yRw7qOFoD3XtjTkYvCvh3zUvNST8DXK/nPaeqIzIv3P3kL3lRJn8iwOiSag==" + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "requires": { + "makeerror": "1.0.12" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true, + "optional": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true, + "optional": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "webpack": { + "version": "5.74.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", + "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.10.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "terser": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz", + "integrity": "sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA==", + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "terser-webpack-plugin": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.5.tgz", + "integrity": "sha512-AOEDLDxD2zylUGf/wxHxklEkOe2/r+seuyOWujejFrIxHf11brA1/dWQNIgXa1c6/Wkxgu7zvv0JhOWfc2ELEA==", + "requires": { + "@jridgewell/trace-mapping": "^0.3.14", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.14.1" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" + } + } + }, + "webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + } + } + }, + "webpack-dev-server": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.10.0.tgz", + "integrity": "sha512-7dezwAs+k6yXVFZ+MaL8VnE+APobiO3zvpp3rBHe/HmWQ+avwh0Q3d0xxacOiBybZZ3syTZw9HXzpa3YNbAZDQ==", + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.1", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.0.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.4.2" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + } + }, + "ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==" + } + } + }, + "webpack-filter-warnings-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", + "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", + "dev": true + }, + "webpack-hot-middleware": { + "version": "2.25.2", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.2.tgz", + "integrity": "sha512-CVgm3NAQyfdIonRvXisRwPTUYuSbyZ6BY7782tMeUzWOO7RmVI2NaBYuCp41qyD4gYCkJyTneAJdK69A13B0+A==", + "dev": true, + "requires": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "webpack-manifest-plugin": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", + "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", + "requires": { + "tapable": "^2.0.0", + "webpack-sources": "^2.2.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" + }, + "webpack-sources": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", + "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", + "requires": { + "source-list-map": "^2.0.1", + "source-map": "^0.6.1" + } + } + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "webpack-virtual-modules": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.4.tgz", + "integrity": "sha512-h9atBP/bsZohWpHnr+2sic8Iecb60GxftXsWNLLLSqewgIsGzByd2gcIID4nXcG+3tNe4GQG3dLcff3kXupdRA==", + "dev": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==" + }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "requires": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.11.1", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.1", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.43.1", + "rollup-plugin-terser": "^7.0.0", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "6.5.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" + }, + "workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "requires": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "requires": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==" + }, + "workbox-webpack-plugin": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-4.3.1.tgz", + "integrity": "sha512-gJ9jd8Mb8wHLbRz9ZvGN57IAmknOipD3W4XNE/Lk/4lqs5Htw4WOQgakQy/o/4CoXQlMCYldaqUg+EJ35l9MEQ==", + "requires": { + "@babel/runtime": "^7.0.0", + "json-stable-stringify": "^1.0.1", + "workbox-build": "^4.3.1" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "strip-comments": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-1.0.2.tgz", + "integrity": "sha512-kL97alc47hoyIQSV165tTt9rG5dn4w1dNnBhOQ3bOU1Nc1hel09jnXANaHJ7vzHLd4Ju8kseDGzlev96pghLFw==", + "requires": { + "babel-extract-comments": "^1.0.0", + "babel-plugin-transform-object-rest-spread": "^6.26.0" + } + }, + "workbox-background-sync": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz", + "integrity": "sha512-1uFkvU8JXi7L7fCHVBEEnc3asPpiAL33kO495UMcD5+arew9IbKW2rV5lpzhoWcm/qhGB89YfO4PmB/0hQwPRg==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-broadcast-update": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-4.3.1.tgz", + "integrity": "sha512-MTSfgzIljpKLTBPROo4IpKjESD86pPFlZwlvVG32Kb70hW+aob4Jxpblud8EhNb1/L5m43DUM4q7C+W6eQMMbA==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-build": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-4.3.1.tgz", + "integrity": "sha512-UHdwrN3FrDvicM3AqJS/J07X0KXj67R8Cg0waq1MKEOqzo89ap6zh6LmaLnRAjpB+bDIz+7OlPye9iii9KBnxw==", + "requires": { + "@babel/runtime": "^7.3.4", + "@hapi/joi": "^15.0.0", + "common-tags": "^1.8.0", + "fs-extra": "^4.0.2", + "glob": "^7.1.3", + "lodash.template": "^4.4.0", + "pretty-bytes": "^5.1.0", + "stringify-object": "^3.3.0", + "strip-comments": "^1.0.2", + "workbox-background-sync": "^4.3.1", + "workbox-broadcast-update": "^4.3.1", + "workbox-cacheable-response": "^4.3.1", + "workbox-core": "^4.3.1", + "workbox-expiration": "^4.3.1", + "workbox-google-analytics": "^4.3.1", + "workbox-navigation-preload": "^4.3.1", + "workbox-precaching": "^4.3.1", + "workbox-range-requests": "^4.3.1", + "workbox-routing": "^4.3.1", + "workbox-strategies": "^4.3.1", + "workbox-streams": "^4.3.1", + "workbox-sw": "^4.3.1", + "workbox-window": "^4.3.1" + } + }, + "workbox-cacheable-response": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-4.3.1.tgz", + "integrity": "sha512-Rp5qlzm6z8IOvnQNkCdO9qrDgDpoPNguovs0H8C+wswLuPgSzSp9p2afb5maUt9R1uTIwOXrVQMmPfPypv+npw==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-core": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-4.3.1.tgz", + "integrity": "sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg==" + }, + "workbox-expiration": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-4.3.1.tgz", + "integrity": "sha512-vsJLhgQsQouv9m0rpbXubT5jw0jMQdjpkum0uT+d9tTwhXcEZks7qLfQ9dGSaufTD2eimxbUOJfWLbNQpIDMPw==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-google-analytics": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-4.3.1.tgz", + "integrity": "sha512-xzCjAoKuOb55CBSwQrbyWBKqp35yg1vw9ohIlU2wTy06ZrYfJ8rKochb1MSGlnoBfXGWss3UPzxR5QL5guIFdg==", + "requires": { + "workbox-background-sync": "^4.3.1", + "workbox-core": "^4.3.1", + "workbox-routing": "^4.3.1", + "workbox-strategies": "^4.3.1" + } + }, + "workbox-navigation-preload": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-4.3.1.tgz", + "integrity": "sha512-K076n3oFHYp16/C+F8CwrRqD25GitA6Rkd6+qAmLmMv1QHPI2jfDwYqrytOfKfYq42bYtW8Pr21ejZX7GvALOw==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-precaching": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-4.3.1.tgz", + "integrity": "sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-range-requests": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-4.3.1.tgz", + "integrity": "sha512-S+HhL9+iTFypJZ/yQSl/x2Bf5pWnbXdd3j57xnb0V60FW1LVn9LRZkPtneODklzYuFZv7qK6riZ5BNyc0R0jZA==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-routing": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-4.3.1.tgz", + "integrity": "sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-strategies": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-4.3.1.tgz", + "integrity": "sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-streams": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-4.3.1.tgz", + "integrity": "sha512-4Kisis1f/y0ihf4l3u/+ndMkJkIT4/6UOacU3A4BwZSAC9pQ9vSvJpIi/WFGQRH/uPXvuVjF5c2RfIPQFSS2uA==", + "requires": { + "workbox-core": "^4.3.1" + } + }, + "workbox-sw": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-4.3.1.tgz", + "integrity": "sha512-0jXdusCL2uC5gM3yYFT6QMBzKfBr2XTk0g5TPAV4y8IZDyVNDyj1a8uSXy3/XrvkVTmQvLN4O5k3JawGReXr9w==" + }, + "workbox-window": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-4.3.1.tgz", + "integrity": "sha512-C5gWKh6I58w3GeSc0wp2Ne+rqVw8qwcmZnQGpjiek8A2wpbxSJb1FdCoQVO+jDJs35bFgo/WETgl1fqgsxN0Hg==", + "requires": { + "workbox-core": "^4.3.1" + } + } + } + }, + "workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", + "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "requires": { + "microevent.ts": "~0.1.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "x-default-browser": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/x-default-browser/-/x-default-browser-0.4.0.tgz", + "integrity": "sha512-7LKo7RtWfoFN/rHx1UELv/2zHGMx8MkZKDq1xENmOCTkfIqZJ0zZ26NEJX8czhnPXVcqS0ARjjfJB+eJ0/5Cvw==", + "dev": true, + "requires": { + "default-browser-id": "^1.0.4" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "xmlhttprequest-ssl": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", + "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yeast": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", + "integrity": "sha512-8HFIh676uyGYP6wP13R/j6OJ/1HwJ46snpvzE7aHAN3Ryqh2yX6Xox2B4CUmTwwOIzlG3Bs7ocsP5dZH/R1Qbg==" + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + }, + "zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "dev": true + } + } +} diff --git a/twake/frontend/package.json b/twake/frontend/package.json index 0432a462d0..0956e1e60e 100644 --- a/twake/frontend/package.json +++ b/twake/frontend/package.json @@ -4,17 +4,30 @@ "repository": "https://github.com/Twake/Twake", "license": "AGPL-3.0", "scripts": { - "dev:start": "craco start", + "dev:frontend": "craco start", + "dev:tailwind": "npx tailwindcss -i ./src/tailwind.css -o ./public/styles/tailwind.css --watch", + "dev:start": "concurrently \"npm run dev:frontend\" \"npm run dev:tailwind\"", "dev:test": "craco test", - "dev:build": "CI=false craco --max_old_space_size=4096 build", "dev:prettier": "prettier --write src/", "dev:linter": "eslint src/", - "start": "craco start", - "test": "CI=true craco test", - "build": "CI=false craco --max_old_space_size=4096 --optimize-for-size build" + "test": "CI=true craco test --passWithNoTests", + "start": "npm run dev:start", + "build": "npm run build-storybook && CI=false craco --max_old_space_size=4096 --optimize-for-size build", + "build-storybook": "build-storybook -o public/storybook", + "storybook": "concurrently \"start-storybook -p 6006 -s public\" \"npm run dev:tailwind\"" }, "eslintConfig": { - "extends": "eslint-config-react-app-eslint-six" + "extends": "eslint-config-react-app-eslint-six", + "overrides": [ + { + "files": [ + "**/*.stories.*" + ], + "rules": { + "import/no-anonymous-default-export": "off" + } + } + ] }, "browserslist": { "production": [ @@ -55,10 +68,10 @@ "@ant-design/icons": "^4.2.2", "@babel/preset-env": "^7.8.7", "@babel/preset-es2017": "^7.0.0-beta.53", - "@craco/craco": "^5.6.4", - "@fortawesome/fontawesome-svg-core": "^1.2.30", - "@fortawesome/free-solid-svg-icons": "^5.14.0", - "@fortawesome/react-fontawesome": "^0.1.11", + "@craco/craco": "^6.4.3", + "@fortawesome/fontawesome-svg-core": "^6.1.2", + "@fortawesome/free-solid-svg-icons": "^6.1.2", + "@fortawesome/react-fontawesome": "^0.2.0", "@fullcalendar/core": "4.4.2", "@fullcalendar/daygrid": "4.4.2", "@fullcalendar/interaction": "4.4.2", @@ -66,8 +79,9 @@ "@fullcalendar/moment": "4.4.2", "@fullcalendar/moment-timezone": "4.4.2", "@fullcalendar/react": "4.4.2", - "@fullcalendar/rrule": "4.4.2", "@fullcalendar/timegrid": "4.4.2", + "@headlessui/react": "^1.6.4", + "@heroicons/react": "^1.0.6", "@iconscout/react-unicons": "^1.1.5", "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", @@ -78,10 +92,10 @@ "@stripe/react-stripe-js": "^1.0.3", "@stripe/stripe-js": "^1.0.3", "@svgr/webpack": "4.3.3", + "@tailwindcss/forms": "^0.5.2", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", - "@types/antd": "^1.0.0", "@types/crypto-js": "^3.1.43", "@types/emoji-mart": "^3.0.2", "@types/emojione": "^2.2.6", @@ -89,7 +103,7 @@ "@types/enzyme-adapter-react-16": "^1.0.6", "@types/jest": "^24.0.0", "@types/lodash": "^4.14.172", - "@types/node": "^12.20.23", + "@types/node": "^12.20.46", "@types/react": "^16.9.0", "@types/react-dom": "^16.9.0", "@types/react-redux": "^7.1.7", @@ -98,15 +112,17 @@ "@types/redux": "^3.6.31", "@types/semaphore": "^1.1.0", "@types/socket.io-client": "^1.4.34", + "@types/tailwindcss": "^3.0.10", "@types/uuid": "^8.3.0", - "@typescript-eslint/eslint-plugin": "^2.10.0", - "@typescript-eslint/parser": "^4.30.0", + "@typescript-eslint/eslint-plugin": "^5.28.0", + "@typescript-eslint/parser": "^5.28.0", "anchorme": "1.1.2", "animated-scroll-to": "^2.0.12", - "antd": "^4.16.5", + "antd": "^4.18.7", + "assert": "^2.0.0", + "await-lock": "^2.2.2", "babel-cli": "^6.26.0", "babel-core": "^6.26.3", - "babel-eslint": "^10.1.0", "babel-plugin-import": "^1.13.0", "babel-plugin-named-asset-import": "^0.3.6", "babel-plugin-syntax-trailing-function-commas": "^6.22.0", @@ -118,9 +134,12 @@ "camelcase": "^5.3.1", "case-sensitive-paths-webpack-plugin": "2.3.0", "classnames": "^2.3.1", - "craco-less": "^1.17.0", + "concurrently": "^7.2.1", + "craco-less": "^2.0.0", "crypto-js": "^4.0.0", "css-loader": "3.6.0", + "custom-protocol-check": "^1.3.0", + "detect-browser": "^5.3.0", "dotenv": "8.2.0", "dotenv-expand": "5.1.0", "draft-js": "^0.11.7", @@ -128,17 +147,19 @@ "draft-js-import-markdown": "^1.4.0", "draftjs-utils": "^0.10.2", "emoji-mart": "^3.0.0", + "emoji-name-map": "^1.2.9", "emojione": "^4.5.0", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.5", + "eslint": "^8.17.0", "eslint-config-react-app": "^5.2.0", "eslint-config-react-app-eslint-six": "^4.0.2", "eslint-loader": "3.0.3", "eslint-plugin-flowtype": "4.7.0", "eslint-plugin-import": "2.23.4", "eslint-plugin-jsx-a11y": "6.4.1", - "eslint-plugin-react": "7.25.1", - "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-react": "^7.30.0", + "eslint-plugin-react-hooks": "^4.5.0", "events": "^3.2.0", "feather-icons": "^4.28.0", "fetch-polyfill": "^0.8.2", @@ -164,13 +185,13 @@ "markdown-to-jsx": "^7.1.5", "mini-css-extract-plugin": "0.12.0", "minimongo": "^6.10.0", - "moment": "^2.27.0", - "moment-timezone": "^0.5.31", - "node-sass": "^6.0.1", + "moment": "^2.29.4", + "moment-timezone": "^0.5.4", "oidc-client": "^1.11.5", "oidc-react": "^1.5.1", "optimize-css-assets-webpack-plugin": "5.0.3", "pnp-webpack-plugin": "1.6.4", + "postcss-100vh-fix": "^1.0.2", "postcss-flexbugs-fixes": "4.2.1", "postcss-loader": "3.0.0", "postcss-normalize": "8.0.1", @@ -187,13 +208,16 @@ "react-fastclick": "^3.0.2", "react-feather": "^2.0.8", "react-google-login": "^5.1.1", - "react-i18next": "^11.11.1", + "react-highlight-words": "^0.18.0", + "react-i18next": "^11.15.3", "react-moment": "^0.9.7", "react-outside-click-handler": "^1.3.0", + "react-page-visibility": "^7.0.0", "react-perfect-scrollbar": "^1.5.8", + "react-player": "^2.10.1", "react-redux": "^7.2.0", "react-router-dom": "^5.2.0", - "react-scripts": "^4.0.0", + "react-scripts": "5.0.1", "react-scrollbar": "^0.5.6", "react-shortcuts": "^2.1.0", "react-showdown": "^2.1.0", @@ -205,13 +229,13 @@ "react-textarea-autosize": "^8.2.0", "react-transition-group": "^4.4.1", "react-virtualized": "^9.22.2", - "react-virtuoso": "1.11.1", + "react-virtuoso": "2.10.2", + "react-zoom-pan-pinch": "^2.1.3", "recoil": "^0.4.0", "redux": "^4.0.5", "resize-observer-polyfill": "^1.5.1", "resolve": "1.19.0", "resolve-url-loader": "3.1.2", - "rrule": "2.6.8", "sass-loader": "8.0.2", "semaphore": "^1.1.0", "semver": "6.3.0", @@ -219,20 +243,43 @@ "shortcuts": "^1.6.1", "socket.io-client": "^2.3.1", "style-loader": "0.23.1", + "tailwindcss": "^3.1.2", "terser-webpack-plugin": "3.1.0", "ts-pnp": "1.2.0", "typescript": "~3.9.7", "url-loader": "2.3.0", - "url-parse": "^1.4.5", + "url-parse": "^1.5.9", "uuid": "^8.3.1", + "uuid-time": "^1.0.0", "workbox-webpack-plugin": "4.3.1" }, "devDependencies": { "@babel/core": "^7.8.7", + "@storybook/addon-actions": "^6.5.9", + "@storybook/addon-docs": "^6.5.9", + "@storybook/addon-essentials": "^6.5.9", + "@storybook/addon-interactions": "^6.5.9", + "@storybook/addon-links": "^6.5.9", + "@storybook/addon-postcss": "^2.0.0", + "@storybook/builder-webpack5": "^6.5.9", + "@storybook/cli": "^6.5.9", + "@storybook/manager-webpack5": "^6.5.9", + "@storybook/node-logger": "^6.5.9", + "@storybook/preset-create-react-app": "^4.1.2", + "@storybook/react": "^6.5.9", + "@storybook/testing-library": "^0.0.13", "@types/draft-js": "^0.11.2", "@types/is-url": "^1.2.28", "@types/markdown-draft-js": "^2.2.3", + "@types/react-page-visibility": "^6.4.1", + "babel-plugin-named-exports-order": "^0.0.2", "craco-alias": "^2.1.1", - "prettier": "^2.0.5" + "eslint-plugin-storybook": "^0.5.12", + "prettier": "^2.0.5", + "prop-types": "^15.8.1", + "sass": "^1.49.9", + "storybook-dark-mode": "^1.1.0", + "storybook-preset-craco": "^0.0.6", + "webpack": "5" } } diff --git a/twake/frontend/postcss.config.js b/twake/frontend/postcss.config.js new file mode 100644 index 0000000000..1ef4ef2a79 --- /dev/null +++ b/twake/frontend/postcss.config.js @@ -0,0 +1,8 @@ +// postcss.config.js +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + require('postcss-100vh-fix'), + }, +}; diff --git a/twake/frontend/public/.well-known/assetlinks.json b/twake/frontend/public/.well-known/assetlinks.json index 3699243087..e25c80ab0a 100644 --- a/twake/frontend/public/.well-known/assetlinks.json +++ b/twake/frontend/public/.well-known/assetlinks.json @@ -1,13 +1 @@ -[ - { - "relation": ["delegate_permission/common.handle_all_urls"], - "target": { - "namespace": "android_app", - "package_name": "com.twake.twake", - "sha256_cert_fingerprints": [ - "E5:26:98:12:06:5D:7A:82:55:FA:19:0B:64:1D:EE:AC:7D:F8:BD:97:18:42:58:48:AB:E9:91:75:88:32:5C:03", - "3F:A6:0E:29:87:A4:0E:EA:12:02:16:8F:DA:76:86:22:F0:64:EB:2D:14:3D:6F:92:D6:F4:16:CB:DA:69:53:2C" - ] - } - } -] +[{"relation":["delegate_permission/common.handle_all_urls"],"target":{"namespace":"android_app","package_name":"com.twake.twake","sha256_cert_fingerprints":["E5:26:98:12:06:5D:7A:82:55:FA:19:0B:64:1D:EE:AC:7D:F8:BD:97:18:42:58:48:AB:E9:91:75:88:32:5C:03","3F:A6:0E:29:87:A4:0E:EA:12:02:16:8F:DA:76:86:22:F0:64:EB:2D:14:3D:6F:92:D6:F4:16:CB:DA:69:53:2C"]}}] diff --git a/twake/frontend/public/index.html b/twake/frontend/public/index.html index 9ec6b96aa1..f533dbd83a 100644 --- a/twake/frontend/public/index.html +++ b/twake/frontend/public/index.html @@ -95,7 +95,7 @@ - + diff --git a/twake/frontend/public/locales/de.json b/twake/frontend/public/locales/de.json index 00a1c730d6..3864544fc9 100644 --- a/twake/frontend/public/locales/de.json +++ b/twake/frontend/public/locales/de.json @@ -190,7 +190,7 @@ "scenes.app.workspaces.welcome_page.create_my_company": "Schaffe meine Firma", "scenes.app.workspaces.welcome_page.lets_go": "Lass uns gehen!", "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Sie wurden möglicherweise mit einer anderen E-Mail-Adresse eingeladen?", - "scenes.app.workspaces.welcome_page.no_company_subtitle": "Hum... Niemand hat Sie zu irgendeiner Arbeitsplatz eingeladen.", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Noch hat Sie niemand zu irgendeiner Firma eingeladen.", "scenes.app.workspaces.welcome_page.ready_to_work": "Sie können jetzt arbeiten.", "scenes.app.workspaces.welcome_page.see_you_soon": "Wir sehen uns!", "scenes.app.workspaces.welcome_page.try_again": "Versuchen Sie es nochmal", @@ -241,7 +241,7 @@ "scenes.app.channelsbar.channel_leaving": "Kanal verlassen", "scenes.app.channelsbar.channel_removing": "Kanal löschen", "scenes.app.channelsbar.channelsuser.new_private_discussion": "Neue private Diskussion", - "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Keine private Nachricht, laden Sie Ihre Mitarbeiter ein !", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Keine private Nachricht, laden Sie Ihre Mitarbeiter ein!", "scenes.app.channelsbar.channelsuser.private_messages": "Private Nachrichten", "scenes.app.channelsbar.channelsworkspace.channel_title": "KANÄLE", "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "Favoriten", @@ -835,5 +835,76 @@ "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Erfolgreich in die Zwischenablage kopiert", "scenes.app.popup.adduser.magiclinks.genrator_info": "Einladungslink zum Arbeitsbereich", "scenes.app.popup.adduser.magiclinks.action_copy": "Kopieren", - "scenes.app.popup.adduser.magiclinks.action_generate": "Generieren" + "scenes.app.popup.adduser.magiclinks.action_generate": "Generieren", + "scenes.join.loading": "Wird geladen …", + "scenes.join.wrong_link_title": "Dieser Link ist nicht mehr verfügbar", + "scenes.join.wrong_link_description": "Bitten Sie die Person, die Sie eingeladen hat, diesem Unternehmen beizutreten, um einen neuen Link oder gründen Sie Ihr eigenes Unternehmen", + "scenes.join.join_workspace_from_company": "Treten Sie {{$1}} von {{$2}} bei!", + "scenes.join.twake_description": "Twake ist ein digitaler quelloffener Arbeitsbereich, der die Produktivität Ihres Teams verbessert", + "scenes.join.login_first_button": "Melden Sie sich an oder erstellen Sie zunächst ein Konto", + "scenes.join.join_the_team_button": "Treten Sie dem Team bei", + "scenes.join.create_the_company_button": "Das Unternehmen erstellen", + "\"": "\"", + "login.login_error": "Fehler bei der Anmeldung", + "'": "'", + "login.create_account": "Konto erstellen", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} schreibt gerade...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} und {{$2}} schreiben...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} und {{$3}} weitere Benutzer schreiben...", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Niemand hat Sie bisher zu einem Arbeitsbereich eingeladen.", + "scenes.apps.messages.message.types.no_message_in_thread": "Es hat noch niemand geantwortet.", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Schreiben Sie mindestens drei Buchstaben, um Benutzer anzuzeigen", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Standardarbeitsbereich", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Alle Workspace-Benutzer automatisch zu diesem Kanal einladen", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Sie sind im Begriff, {{$1}} zu löschen", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Du hast noch {{$1}} Mitglieder in {{$2}}. Sie sollten alle Mitglieder entfernen, um diesen Arbeitsbereich löschen zu können.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Mir ist bewusst, dass alle Nachrichten und Dateien meines Arbeitsbereichs gelöscht werden.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Die maximale Logogröße beträgt 5 MB", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Schlechtes Format, nur png gif und jpg sind erlaubt", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Unbekannter Fehler", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Fehler", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Kein Benutzer gefunden", + "scenes.app.channelsbar.currentuser.reset": "Zurücksetzen", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Keine Emojis gefunden", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Kein Befehl gefunden", + "components.locked_features_components.locked_invite_alert.message_part_1": "Ihr Unternehmen hat die maximale Anzahl von {{$1}} Mitgliedern erreicht. Bitte ", + "components.locked_features_components.locked_invite_alert.message_link": "aktualisieren Sie Ihr Unternehmen", + "components.locked_features_components.locked_invite_alert.message_part_2": ", um weitere Mitglieder einzuladen.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " wenden Sie sich an den Eigentümer oder Verwalter Ihres Unternehmens.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Alle Mitglieder meines Unternehmens auf der Konsole sehen", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Beschreiben Sie Ihre Bewerbung in wenigen Worten", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Neue Integration", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Mir ist bekannt, dass der Inhaber und die Verwalter dieses Unternehmens diesen Antrag ändern und veröffentlichen können.", + "twake.application.access.title": "Wählen Sie die richtigen Bereiche für Ihre Anwendung.", + "twake.application.access.no_default_scopes_available'": "Diese Integration hat keinen Zugang zu {{$1}}", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "die Twake-API-Dokumentation", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Wenn Sie nicht wissen, wie Sie diese ausfüllen sollen, gehen Sie zu ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Privat Schlüssel", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Anwendung {{$1}} erfolgreich entfernt!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Fehler beim Entfernen der Anwendung {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Erfolgreiche {{$1}} Bewerbung!", + "scenes.app.integrations_parameters.add_application": "Neue Einbindung", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Entwicklereinstellungen", + "components.rich_text_editor.plugins.suggestions.loading": "Auf der Suche nach mehr", + "components.open_desktop_popup.subtitle": "in der Twake-App geöffnet", + "components.open_desktop_popup.open_here_link": "Öffnen Sie stattdessen hier", + "molecules.download_banner.title": "Holen Sie das Beste aus Twake heraus, laden Sie jetzt die Desktop-App herunter", + "molecules.download_banner.download_button": "Laden Sie die Desktop-App herunter", + "scenes.app.channelsbar.channel_copy_link": "Kanallink kopieren", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Erfolgreich aktualisiert", + "components.searchpopup.files": "Dateien", + "components.searchpopup.recent_chats": "Aktuelle Chats", + "components.searchpopup.recent_media": "Aktuelle Medien", + "components.searchpopup.recent_files": "Aktuelle Dateien", + "components.searchpopup.no_results_for": "Es gab keine Ergebnisse für", + "components.searchpopup.try_new_search": "Versuchen Sie eine neue Suche", + "components.searchpopup.all": "Alle", + "components.searchpopup.chats": "Chats", + "components.searchpopup.media": "Medien", + "components.searchpopup.recent_channels_and_contacts": "Letzte Kanäle und Kontakte", + "components.searchpopup.header_title": "Suche", + "components.searchpopup.scope.company": "in aller Gesellschaft", + "components.searchpopup.scope.channel": "in diesem Kanal", + "components.searchpopup.channels": "Kanäle", + "components.searchpopup.messages": "Mitteilungen" } diff --git a/twake/frontend/public/locales/en.json b/twake/frontend/public/locales/en.json index 92f8aeb391..a1d80d4099 100644 --- a/twake/frontend/public/locales/en.json +++ b/twake/frontend/public/locales/en.json @@ -92,6 +92,7 @@ "scenes.apps.drive.right_preview.operations_delete": "Move to trash", "scenes.apps.drive.right_preview.public_link": "Public link", "scenes.apps.messages.messages": "Messages", + "scenes.apps.messages.jump": "Jump to message", "scenes.apps.messages.chatbox.chat.delete_message": "Delete this message", "scenes.apps.messages.chatbox.chat.delete_message_btn": "Delete message", "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Name", @@ -103,10 +104,11 @@ "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}} only", "scenes.apps.messages.left_bar.stream.notifications.never": "Nothing", "scenes.apps.parameters.workspace_sections.workspace": "Workspace", - "scenes.apps.parameters.workspace_sections.members": "Participants", + "scenes.apps.parameters.workspace_sections.members": "Channel participants", "scenes.apps.parameters.group_sections.workspaces": "Workspaces", "scenes.apps.parameters.group_sections.apps": "Apps", "scenes.apps.account.title": "Account parameters", + "scenes.apps.account.on_console": "To edit your global account preferences, click on Go to Console.", "scenes.apps.account.account.menu_title": "Account", "scenes.apps.account.languages.menu_title": "Language", "scenes.apps.account.account.firstname": "First name", @@ -124,6 +126,12 @@ "scenes.apps.account.account.password_modal.bad_password": "Your passwords do not match or they are too short. Please type a password with at least 8 characters.", "scenes.apps.account.account.logout": "Logout", "scenes.apps.account.languages.text": "Change Twake language.", + "scenes.apps.account.assistant.title": "Assistant", + "scenes.apps.account.assistant.description": "Twake assistant is able to make sense of your everyday work on Twake and provide smart shortcuts and actions during your day. The assistant is part of the Work@Home initiative https://workathome.linagora.com/ and is currently being tested only in the Linagora company and is in the learning phase. It means we will send Twake usage data in order to train our future assistant feature.", + "scenes.apps.account.assistant.share.nothing": "Do not share anything with the assistant (disable assistant)", + "scenes.apps.account.assistant.share.all": "Share everything including messages and files contents", + "scenes.apps.account.assistant.share.metadata": "Share metadata but not contents", + "scenes.apps.account.assistant.success": "Your preferences have been updated with success.", "scenes.apps.account.notifications.title": "Notifications", "scenes.apps.account.notifications.keywords_subtitle": "Keywords", "scenes.apps.account.notifications.keywords_placeholder": "dev, wifi, code, ...", @@ -293,6 +301,7 @@ "scenes.app.channelsbar.guest_management": "Guest management", "scenes.app.channelsbar.read_sign": "Mark as read", "scenes.app.channelsbar.unread_sign": "Mark as unread", + "scenes.app.channelsbar.channel_copy_link": "Copy channel link", "scenes.app.channelsbar.channel_leaving": "Leave channel", "scenes.app.channelsbar.channel_removing": "Delete channel", "scenes.app.channelsbar.company_invitation_alert_subtitle": "You can import these channels into your business to stay organized by clicking on this frame.", @@ -327,7 +336,7 @@ "scenes.app.popup.appsparameters.pages.app_modification_right": "All managers of this company will be able to edit this application.", "scenes.app.popup.appsparameters.pages.app_privileges_information": "Define what your application can edit and read.", "scenes.app.popup.appsparameters.pages.app_privileges_label": "Application privileges", - "scenes.app.popup.appsparameters.pages.app_update": "Update the app {{$1}} (the app is used {{$2}} times.)", + "scenes.app.popup.appsparameters.pages.app_update": "Update the app {{$1}} (the app is used {{$2}} times)", "scenes.app.popup.appsparameters.pages.application_title": "Application", "scenes.app.popup.appsparameters.pages.apps_title": "Your applications and connectors", "scenes.app.popup.appsparameters.pages.automatique_label": "Automatic", @@ -391,15 +400,21 @@ "scenes.app.popup.createworkspacepage.add_subtitle": "Need more space?", "scenes.app.popup.createworkspacepage.create_new_workspace": "Create a new workspace", "scenes.app.popup.createworkspacepage.placeholder_name": "Name of the workspace", - "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Set the frequency of mobile notifications.", + "scenes.app.popup.userparameter.pages.email_notif_delay_never": "Never", + "scenes.app.popup.userparameter.pages.email_notif_delay_quarter_hour": "15 minutes", + "scenes.app.popup.userparameter.pages.email_notif_delay_one_day": "1 day", + "scenes.app.popup.userparameter.pages.email_notif_delay_one_hour": "1 hour", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Configure mobile push notifications.", "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Frenquency of notifications", "scenes.app.popup.userparameter.pages.keywords_notif_description": "Highlight the following keywords:", - "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Set the frequency of email notifications.", - "scenes.app.popup.userparameter.pages.private_message_content.show": "Show private messages content", - "scenes.app.popup.userparameter.pages.private_message_content.hide": "Hide private messages content", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Configure email notifications digest.", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Hide the content of messages in push notifications", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Replace push notification content with '[Private]'", "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Choose a period during which you do not receive notifications.", "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Do not disturb at night", "scenes.app.popup.userparameter.pages.notif_content_label": "Content of notifications", + "scenes.app.popup.userparameter.pages.notification_sound.defaut": "Default", + "scenes.app.popup.userparameter.pages.notification_sound.none": "None", "scenes.app.mainview.quick_search_placeholder": "Quick search", "scenes.app.popup.userparameter.personnal_workspaces_title": "Your workspaces", "scenes.app.popup.workspaceparameter.admin_current_status": "You are an Administrator.", @@ -425,7 +440,7 @@ "scenes.app.popup.workspaceparameter.pages.company_name_description": "Change the name of this company", "scenes.app.popup.workspaceparameter.pages.company_name_label": "Name of the company", "scenes.app.popup.workspaceparameter.pages.configuration_notif": "configuration", - "scenes.app.popup.workspaceparameter.pages.configure_button": "Configure", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Preferences ", "scenes.app.popup.workspaceparameter.pages.description": "Description", "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Applications developed by the company", "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Display preferences", @@ -540,10 +555,11 @@ "scenes.apps.messages.message.reply_button": "Reply", "scenes.apps.messages.message.save_button": "Save", "scenes.apps.messages.message.show_button": "Display", - "scenes.apps.messages.message.show_responses_button": "View all answers", + "scenes.apps.messages.message.show_responses_button": "See previous answers", "scenes.apps.messages.message.types.first_channel_message_text": "This is the first message of the channel", "scenes.apps.messages.message.types.first_message_text": "This is the first message", "scenes.apps.messages.message.types.no_message_in_thread": "Nobody replied yet.", + "scenes.apps.messages.message.user_deactivated": "You are viewing the archives of a deactivated account", "scenes.apps.messages.messageslist.get_writing_user": "is writing...", "scenes.apps.messages.messageslist.get_writing_users": "are writing...", "scenes.apps.messages.messageslist.go_last_message_button": "Go to last message", @@ -564,10 +580,10 @@ "services.apps.messages.no_command_possible": "We can not execute the command '{{$1}}' because '{{$2}}' does not exist or does not allow to create commands.", "services.user.notification_parameters_update_alert": "The notification settings have been updated.", "services.user.update_password_alert": "Your password has been updated.", - "'": "", - "\"": "", - "login.create_account": "", - "login.login_error": "", + "'": "'", + "\"": "\"", + "login.create_account": "Create account", + "login.login_error": "Error during login", "scenes.app.workspaces.components.skip": "Skip", "scenes.apps.calendar.unconfigured_tab": "This tab is not configured yet.", "scenes.apps.drive.trash": "Trash", @@ -624,6 +640,7 @@ "components.workspace.list_manager.current_company": "Current company", "components.workspace.list_manager.all": "All", "components.workspace.calendar.invalid": "Invalid", + "components.searchpopup.header_title": "Search", "components.searchpopup.enter_text": "Enter some text to search Twake.", "components.searchpopup.loading": "Loading more results", "components.searchpopup.filter_ws": "Filter workspaces", @@ -642,6 +659,22 @@ "components.searchpopup.hide_filters": "hide filters", "components.searchpopup.show_filters": "show filters", "components.searchpopup.load_more": "Load more results", + "components.searchpopup.start_search": "Enter few keywords to start the search.", + "components.searchpopup.no_results_for": "There were no results for", + "components.searchpopup.try_new_search": "Try a new search", + "components.searchpopup.scope.company": "in all company", + "components.searchpopup.scope.channel": "in this channel", + "components.searchpopup.all": "All", + "components.searchpopup.chats": "Chats", + "components.searchpopup.channels": "Channels", + "components.searchpopup.messages": "Messages", + "components.searchpopup.media": "Media", + "components.searchpopup.files": "Files", + "components.searchpopup.see_more": "See more", + "components.searchpopup.recent_chats": "Recent chats", + "components.searchpopup.recent_media": "Recent media", + "components.searchpopup.recent_files": "Recent files", + "components.searchpopup.recent_channels_and_contacts": "Recent channels and contacts", "general.more": "More", "scenes.apps.board.archived_tasks": "Archived tasks ({{$1}})", "scenes.apps.board.active_tasks": "Active tasks", @@ -691,6 +724,15 @@ "scenes.client.channelbar.channelmemberslist.title": "Users in {{$1}}", "scenes.client.channelbar.channelmemberslist.loader": "Load more", "scenes.client.channelbar.channelmemberslist.autocomplete": "Search users", + "scenes.client.channelbar.channelmemberslist.search_invite": "Search and invite users to this channel", + "scenes.client.channelbar.channelmemberslist.search_invite_notice": "There is not a lot of members in this channel. Search and invite users now by email or name.", + "scenes.client.channelbar.channelmemberslist.invite_email_button": "Add to channel only as guest", + "scenes.client.channelbar.channelmemberslist.invite_email_button_workspace": "Add to channel and workspace as member", + "scenes.client.channelbar.channelmemberslist.invite_email_button_workspace_confirm": "Invite {{$1}} to workspace as member?", + "scenes.client.channelbar.channelmemberslist.search_invite_type_email": "Type a valid addess to invite by email.", + "scenes.client.channelbar.channelmemberslist.pending_section": "Users pending invitation", + "scenes.client.channelbar.channelmemberslist.members_section": "Users in this channel", + "scenes.client.channelbar.channelmemberslist.not_members_section": "Users not in this channel", "scenes.client.channelbar.channelmemberslist.menu.option_2": "Remove from channel", "components.leftbar.channel.workspaceschannels.menu.option_1": "Create a channel", "components.leftbar.channel.workspaceschannels.menu.option_2": "Join a channel", @@ -724,10 +766,15 @@ "scenes.client.channelbar.channelmemberslist.tag": "You", "components.alert.leave_private_channel.title": "Are you sure you want to leave the channel ?", "components.alert.leave_private_channel.description": "You will not be able to join this private channel again unless someone invite you.", + "scenes.client.join_private_channel.info": "This content of this channel is restricted or doesn't exist. Please contact a member of this channel to get invited.", + "scenes.client.join_public_channel": "Join this channel", + "scenes.client.join_public_channel.info": "You are not a member of this direct channel. Click this button to start the discussion now.", "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "You are not a member", "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Load more", "general.re_send": "Re-send", "general.verify": "Verify", + "general.yes": "Yes", + "general.no": "No", "components.unverified_account.typography_text_danger": "Please verify your account within {{$1}} days. If not, your account will be blocked after 7 days and permanently deleted after 30 days. You can verify your account through the verification email.", "components.unverified_account.verification_details": "We have sent verification email to", "components.account_verification_status_sentence": "Your account status is: {{$1}}", @@ -757,6 +804,8 @@ "general.user.role.company.member": "Member", "general.user.role.company.guest": "Guest", "general.user.deleted": "Deleted Account", + "general.user.deactivated": "User is no longer in this company", + "general.user.connected": "Online", "components.richtexteditor.toolbar.bold": "Bold", "components.richtexteditor.toolbar.underline": "Underline", "components.richtexteditor.toolbar.italic": "Italic", @@ -835,7 +884,7 @@ "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Website", "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Creation date", "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Version", - "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Show", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Show details", "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Remove from the company", "scenes.app.integrations_parameters.company_applications_table.name": "Name", "scenes.app.integrations_parameters.company_applications_table.title": "Installed in your company", @@ -843,7 +892,7 @@ "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Successfully added {{$1}} in your company", "scenes.apps.messages.input.replied_to": "replied to ", "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Default workspace", - "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Automatically invite all workspace users to this channel", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Automatically invite all new company users to this workspace", "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "You are about to delete {{$1}}", "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "You still have {{$1}} members in {{$2}}. You should remove all the members to be able to delete this workspace.", "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "I understand that all of my workspace's messages and files will be deleted.", @@ -851,6 +900,7 @@ "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Bad format, only png gif and jpg are allowed", "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Unknown error", "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Error", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Successfully updated", "scenes.join.loading": "Loading…", "scenes.join.wrong_link_title": "This link is not available anymore", "scenes.join.wrong_link_description": "Ask the person who invited you to join this company for a new link or create your own company", @@ -859,5 +909,46 @@ "scenes.join.twake_description": "Twake is an open-source digital workspace built to improve your team productivity", "scenes.join.login_first_button": "Log in or create an account first", "scenes.join.join_the_team_button": "Join the team", - "scenes.app.channelsbar.currentuser.reset": "Reset" + "scenes.app.channelsbar.currentuser.reset": "Reset", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Write at least three letters to display users", + "components.rich_text_editor.plugins.suggestions.loading": "Looking for more", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "No user found", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "No emoji found", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "No command found", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} is writing...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} and {{$2}} are writing...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} and {{$3}} more users are writing...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Your company has reached its maximum limit of {{$1}} members. Please ", + "components.locked_features_components.locked_invite_alert.message_link": "upgrade your company", + "components.locked_features_components.locked_invite_alert.message_part_2": " to invite more members.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " contact the owner or administrator of your company.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "See all my company members on the console", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Describe your application in a few words", + "scenes.app.popup.appsparameters.pages.application_creator.title": "New integration", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "I understand that the owner and administrators of this company will be able to modify and publish this application.", + "twake.application.access.title": "Select the right scopes for your application.", + "twake.application.access.no_default_scopes_available'": "This integration doesn't have any {{$1}} access", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "the Twake API documentation", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "If you do not know how to fill these, go to ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Private key", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Successfully removed application {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Error while removing application {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Successfully {{$1}} application!", + "scenes.app.integrations_parameters.add_application": "New integration", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Developer settings", + "components.open_desktop_popup.subtitle": "Opened in Twake app", + "components.open_desktop_popup.open_here_link": "Open in web instead", + "components.open_desktop_popup.open_here_link_forever": "Never try to open app again", + "molecules.download_banner.title": "Get the most out of Twake, download the desktop app now", + "molecules.download_banner.download_button": "Download desktop app", + "components.channel_attachement_list.medias": "Medias", + "components.channel_attachement_list.files": "Files", + "components.channel_attachement_list.title": "Channel files and medias", + "components.channel_attachement_list.open": "Open gallery", + "components.channel_attachement_list.nothing_found": "Nothing here yet", + "molecules.message_quote.deleted": "This message was deleted", + "molecules.quoted_content.attachements": "{{$1}} attachments", + "components.message_seen_by.title": "Users who've seen the message", + "components.message_seen_by.none_seen_it": "No one has seen the message yet", + "components.message_seen_by.btn": "Information" } diff --git a/twake/frontend/public/locales/eo.json b/twake/frontend/public/locales/eo.json new file mode 100644 index 0000000000..031d1fb6e7 --- /dev/null +++ b/twake/frontend/public/locales/eo.json @@ -0,0 +1,910 @@ +{ + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "Materialoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "Kemio", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Komerco / Komerco / Distribuado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Eldonado / Komunikado / Plurmedia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Maŝinaro / Aŭtomobilo", + "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "Komercaj servoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Amuzado / spektakloj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "Tekstilo / Vestaĵo / Ŝuoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Transporto / Loĝistiko", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Nomo", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Aldoni al plej ŝatataj", + "scenes.apps.messages.left_bar.stream.notifications": "Sciigoj…", + "scenes.apps.messages.left_bar.stream.notifications.all": "Ajna mesaĝo", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} kaj {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}} nur", + "scenes.apps.account.account.lastname": "Familia nomo", + "scenes.apps.account.account.username": "Salutnomo", + "scenes.apps.account.account.change_username": "Ŝanĝu vian unikan uzantnomon.", + "scenes.apps.account.account.emails": "Retpoŝtoj", + "scenes.apps.account.account.main_email": "Ĉefa retpoŝto", + "scenes.apps.account.account.email_add": "Aldonu novan retpoŝton", + "scenes.apps.account.account.email_add_modal.invalid_code": "Ĉi tiu kodo estas nevalida", + "scenes.apps.account.notifications.title": "Sciigoj", + "scenes.apps.account.notifications.disturb_option_b": " kaj ", + "scenes.apps.account.notifications.disturb_option_c": " (loka horzono)", + "scenes.apps.account.notifications.devices_subtitle": "Aparataj sciigoj", + "scenes.apps.tasks.task": "Tasko", + "scenes.login.create_account.username": "Salutnomo", + "scenes.login.create_account.username_already_exist": "Ĉi tiu uzantnomo jam estas uzata", + "scenes.login.create_account.fill_in_username": "Vi devas plenigi vian uzantnomon", + "scenes.login.create_account.fill_in_email": "Vi devas plenigi vian retpoŝton per ĝusta retpoŝto", + "scenes.login.create_account.too_short_password": "Via pasvorto devas enhavi almenaŭ 8 signojn.", + "scenes.login.create_account.firstname": "Antaŭnomo", + "scenes.login.forgot_password.text3": "Enigu novan pasvorton por via konto.", + "scenes.login.forgot_password.password": "Pasvorto", + "scenes.login.forgot_password.password2": "Konfirmu pasvorton", + "scenes.login.forgot_password.password_dont_match": "Viaj pasvortoj ne kongruas aŭ ili estas tro mallongaj. Bonvolu tajpi pasvorton kun almenaŭ 8 signoj.", + "scenes.login.home.title": "Ensalutu al Twake", + "scenes.login.home.subtitle": "Feliĉa vidi vin", + "scenes.login.home.email": "Retpoŝto", + "scenes.login.create_account.step_2_subtitle_b": "Via telefonnumero restas privata.", + "scenes.login.create_account.step_3_mail_sent": "Ni sendis al vi aktivigan ligilon retpoŝte.", + "scenes.login.create_account.step_3_subtitle": "Lasta paŝo — ni devas kontroli, ke vi ne estas roboto!", + "scenes.app.workspaces.welcome_page.try_again": "Provu denove", + "scenes.app.workspaces.welcome_page.twake_team": "Twake", + "scenes.app.workspaces.welcome_page.welcome_header": "Bonvenon al Twake!", + "scenes.app.workspaces.welcome_page.other_mail_title": "Malĉefaj adresoj", + "components.calendar.repetition.everyday": "Ĉiutage", + "components.calendar.repetition.does_not_repeat": "Ne ripetas", + "components.calendar.repetition.weekly_on": "Ĉiusemajne je {{$1}}", + "components.calendar.repetition.monthly_on": "Ĉiumonate sur la {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Ĉiumonate tage {{$1}}", + "components.calendar.repetition.annually_on": "Ĉiujare sur {{$1}}", + "components.calendar.repetition.every_weekday": "Ĉiun labortagon (lun al vendredo)", + "components.calendar.repetition.custom": "Propra...", + "components.calendar.repetition.on": "On", + "components.calendar.repetition.after": "Post", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Kreu laborspacon", + "scenes.app.channelsbar.currentuser.invited_status": "Vi estas gasto.", + "scenes.app.channelsbar.currentuser.title": "Kontagordoj", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Agordoj de laborspaco", + "scenes.app.channelsbar.modify_channel_menu": "Redaktu kanalon", + "scenes.app.channelsbar.guest_management": "Gastadministrado", + "scenes.app.channelsbar.read_sign": "Marku kiel legita", + "scenes.app.channelsbar.unread_sign": "Marki kiel nelegita", + "scenes.app.channelsbar.channel_leaving": "Forlasu kanalon", + "scenes.app.channelsbar.channel_removing": "Forigi kanalon", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Difinu kion via aplikaĵo povas redakti kaj legi.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Aplikaj privilegioj", + "scenes.app.popup.appsparameters.pages.app_update": "Ĝisdatigu la apon {{$1}} (la programo estas uzata {{$2}} fojojn)", + "scenes.app.popup.appsparameters.pages.application_title": "Programo", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "Se vi aktivigas 'Aŭtomata', ĉi tiu aplikaĵo aŭtomate estos aldonita al la sekvaj laborspacoj de ĉi tiu kompanio.", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "Permesitaj IP-adresoj", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "La publikigo de via aplikaĵo nuntempe atendas validigon de la teamo de Twake.", + "scenes.app.popup.appsparameters.pages.go_back": "Reen", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Komencu skribante vian mesaĝon en formato JSON.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Interna aplikaĵo", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Iru al la dokumentado por generi vian agordon en formato JSON.", + "scenes.app.popup.appsparameters.pages.loading": "Ŝargante…", + "scenes.app.popup.appsparameters.pages.publication_description": "Determini la videblecon de via aplikaĵo.", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Kaŝi enhavon pri privataj mesaĝoj", + "scenes.app.mainview.quick_search_placeholder": "Rapida serĉo", + "scenes.app.popup.userparameter.personnal_workspaces_title": "Viaj laborspacoj", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Reiru al la serĉo", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Montru preferojn", + "scenes.app.popup.workspaceparameter.pages.install_button": "Instali", + "scenes.apps.messages.message.reply_button": "Respondi", + "scenes.apps.messages.message.save_button": "Konservi", + "scenes.apps.messages.message.show_button": "Montru", + "scenes.apps.messages.message.show_responses_button": "Rigardu ĉiujn respondojn", + "scenes.apps.messages.message.types.first_channel_message_text": "Ĉi tiu estas la unua mesaĝo de la kanalo", + "scenes.login.verifymail.error_message": "Eraro okazis", + "scenes.login.verifymail.signin_button": "Ensaluti", + "scenes.login.verifymail.success": "Via retpoŝto estis sukcese kontrolita!", + "scenes.apps.tasks.board.place_holder": "Nomo de la estraro", + "scenes.apps.tasks.board.tasks.subtask": "Subtasko", + "scenes.apps.tasks.board.tasks.add_subtask": "Aldonu subtaskon", + "scenes.apps.tasks.board.tasks.use_deadline": "Uzu limdaton", + "components.input.copied": "Kopiita", + "components.drive.new_versions": "Aldonu novan version", + "components.drive.navigators.directory_not_found": "Dosierujo ne trovita.", + "components.upload.drop_files": "Forigu viajn dosierojn ĉi tie", + "components.channelworkspacelist.title": "Kanaloj", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} retpoŝto(j) estos aldonitaj", + "components.newversion.new_version_component.row.part_1": "Vi funkcias malmodernan Twake-version", + "components.newversion.new_version_component.row.part_2": "ni sugestas vin reŝargi la apon kaj ĝui niajn novajn funkciojn!", + "components.newversion.new_version_component.link": "Klaku ĉi tie por reŝargi", + "components.newversion.new_version_modal.title": "Nova ĝisdatigo disponebla!", + "scenes.apps.drive.download_all_button": "Elŝutu ĉion", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} aldonis novan {{$2}} langeton {{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} forigis {{$2}} langeton {{$3}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} aldonis novan konektilon {{$2}}", + "components.account_verification_status_sentence": "Via konta stato estas: {{$1}}", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Serĉu gastojn aŭ pritraktatajn retpoŝtojn", + "general.user.deleted": "Forigita Konto", + "components.richtexteditor.toolbar.bold": "Grasa", + "components.richtexteditor.toolbar.underline": "Substreki", + "components.richtexteditor.toolbar.italic": "Kursiva", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Estas problemo kun via firmaa abono. Bonvolu kontakti la posedanton aŭ administranton de la kompanio!", + "general.uploading": "Alŝutante", + "components.emoji_picker.categories.search_result": "Serĉrezultoj", + "components.locked_features.locked_only_office_popup.subtitle": "En la senpaga versio, vi ne povas uzi nur oficejon.", + "components.locked_features.locked_drive_popup.title": "Vi ĵus atingis la veturlimon", + "general.resume": "Rekomenci", + "scenes.app.integrations_parameters.company_application_popup.tag": "Instalita", + "scenes.app.integrations_parameters.company_application_popup.btn": "Instali", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Informoj", + "scenes.join.loading": "Ŝargante…", + "scenes.join.wrong_link_title": "Ĉi tiu ligilo ne plu disponeblas", + "scenes.join.wrong_link_description": "Demandu al la persono, kiu invitis vin aliĝi al ĉi tiu kompanio, pri nova ligilo aŭ kreu vian propran kompanion", + "general.close": "Fermi", + "general.save": "Konservi", + "general.cancel": "Nuligi", + "general.retry": "Reprovi", + "general.create": "Krei", + "general.edit": "Redakti", + "general.continue": "Daŭrigi", + "general.back": "Reen", + "general.confirm": "Konfirmi", + "general.delete": "Forviŝi", + "general.archive": "Enarkivigi", + "general.unarchive": "Elarkivigi", + "general.help": "Helpo", + "general.help.support": "Subteno", + "general.help.documentation": "Dokumentaro", + "general.send": "Sendi mesaĝon", + "general.update": "Ĝisdatigi", + "general.remove": "Forigi", + "general.add": "Aldoni", + "general.connexion_status.disconnected": "Vi estas eksterrete", + "general.connexion_status.connected": "Vi estas enreta", + "general.connexion_status.connecting": "Rekonektante…", + "application.load.longer": "Servilo daŭras pli longe ol atendite por respondi, bonvolu atendi aŭ reŝargi la paĝon...", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Fadeno de mesaĝoj", + "scenes.app.workspaces.create_company.group_data": "Agordu vian novan grupon", + "scenes.app.workspaces.create_company.group_data.group_type": "Speco de grupo", + "scenes.app.workspaces.create_company.group_data.group_type.company": "Firmao aŭ kompania fako", + "scenes.app.workspaces.create_company.group_data.group_type.public_organization": "Publika organizaĵo", + "scenes.app.workspaces.create_company.group_data.group_type.university_school": "Universitato aŭ lernejo", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Societo, klubo aŭ bonfarado", + "scenes.app.workspaces.create_company.group_data.group_type.other_group": "Alia", + "scenes.app.workspaces.create_company.group_data.group_size": "Grando de grupo", + "scenes.app.workspaces.create_company.group_data.group_size.less_3": "Malpli ol 4 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4–10 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11–49 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50–99 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100–499 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500–999 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000–4999 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "Pli ol 5000 uzantoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "Ĉefa agado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Manĝo", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "Banko / asekuro", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Presado / papero", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "Konstruado / konstrumaterialoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "Nemoveblaĵoj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Elektroniko / elektro / energio", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Studoj kaj konsiloj", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "Farmacia industrio", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "IT / Telekomunikado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Esplorado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "Edukado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Administrado", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "Alia", + "components.application.messages": "Mesaĝoj", + "components.drive_dropzone.uploading": "Alŝutante…", + "components.user_picker.modal_no_result": "Neniuj rezultoj trovitaj", + "components.users_picker.add_me": "Aldonu min", + "scenes.app.workspaces.create_company.invitations.title": "Agordu vian laborspacon.", + "scenes.app.header.disconnected": "Vi estas malkonektita", + "scenes.app.header.disconnected.reload": "Reŝargi", + "scenes.app.header.alt_notifications": "Sciigoj", + "scenes.apps.calendar.calendar.week_btn": "Semajno", + "scenes.apps.calendar.calendar.list_btn": "Listo", + "scenes.apps.calendar.event_edition.deadline_tag": "Limdato", + "scenes.apps.calendar.event_edition.checkbox_all_day": "Tuta tago", + "scenes.apps.calendar.event_edition.title_confidentiality": "Konfidenco", + "scenes.apps.calendar.event_view.article_until": "al", + "scenes.apps.calendar.calendar_modal.participants": "Partoprenantoj", + "scenes.apps.calendar.calendar_modal.placeholder": "Nomo", + "scenes.apps.calendar.left.calendars": "Kalendaroj", + "scenes.apps.drive.left.search": "Serĉi", + "scenes.apps.drive.navigators.navigator_content.directory_name": "Dosierujo nomo", + "scenes.apps.drive.navigators.navigator_content.files": "Dosieroj", + "scenes.apps.drive.navigators.navigator_labels.title": "Etikedoj", + "scenes.apps.drive.navigators.new_file.untitled": "Sentitola", + "scenes.apps.drive.navigators.new_file.create_file.type": "Dosiertipo", + "scenes.apps.drive.navigators.new_file": "Nova dosiero", + "scenes.apps.drive.preview_bloc.operations_download": "Elŝuti", + "scenes.apps.drive.preview_bloc.error_file": "Dosiero ne trovita", + "scenes.apps.drive.right_preview.operations_restore": "Restaŭri", + "scenes.apps.drive.right_preview.operations_delete": "Movu al rubujo", + "scenes.apps.drive.right_preview.public_link": "Publika ligilo", + "scenes.apps.messages.messages": "Mesaĝoj", + "scenes.apps.messages.chatbox.chat.delete_message": "Forigu ĉi tiun mesaĝon", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "Forigi mesaĝon", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Forigi el plej ŝatataj", + "scenes.apps.messages.left_bar.stream.notifications.never": "Nenio", + "scenes.apps.parameters.workspace_sections.workspace": "Laborejo", + "scenes.apps.parameters.workspace_sections.members": "Partoprenantoj", + "scenes.apps.parameters.group_sections.workspaces": "Laborejoj", + "scenes.apps.parameters.group_sections.apps": "Programoj", + "scenes.apps.account.title": "Kontaj parametroj", + "scenes.apps.account.account.menu_title": "Konto", + "scenes.apps.account.languages.menu_title": "Lingvo", + "scenes.apps.account.account.firstname": "Antaŭnomo", + "scenes.apps.account.account.password": "Pasvorto", + "scenes.apps.account.account.password_modal.old_password": "Aktuala Pasvorto", + "scenes.apps.account.account.password_modal.password": "Nova pasvorto", + "scenes.apps.account.account.password_modal.bad_old_password": "Malnova pasvorto ne estas ĝusta.", + "scenes.apps.account.account.password_modal.bad_password": "Viaj pasvortoj ne kongruas aŭ ili estas tro mallongaj. Bonvolu tajpi pasvorton kun almenaŭ 8 signoj.", + "scenes.apps.account.account.logout": "Adiaŭi", + "scenes.apps.account.languages.text": "Ŝanĝu Twake-lingvon.", + "scenes.apps.account.notifications.keywords_subtitle": "Ŝlosilvortoj", + "scenes.apps.account.notifications.keywords_placeholder": "dev, wifi, kodo, ...", + "scenes.apps.account.notifications.disturb_option_a": "Ne sendu al mi puŝajn sciigojn inter ", + "scenes.apps.account.notifications.devices_option_ever": "Ĉiam sendu al mi puŝajn sciigojn", + "scenes.apps.account.notifications.devices_option_inactive": "Sendu al mi puŝajn sciigojn kiam mi estas neaktiva sur labortablo", + "scenes.apps.account.notifications.devices_option_never": "Neniam sendu al mi puŝajn sciigojn", + "scenes.apps.account.notifications.privacy_subtitle": "Privateco", + "scenes.apps.account.notifications.mail_subtitle": "Retpoŝtaj sciigoj", + "scenes.apps.account.notifications.sound": "Sona sciigo", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Etendo", + "scenes.apps.parameters.workspace_sections.members.members": "Uzantoj", + "scenes.apps.parameters.workspace_sections.members.pending": "Atendantaj retpoŝtoj", + "scenes.apps.parameters.workspace_sections.members.invite": "Invitu novan uzanton", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "Aldonu uzanton", + "scenes.apps.tasks.boards": "Tabuloj", + "scenes.apps.tasks.connectors_menu": "Konektiloj…", + "scenes.apps.tasks.connectors_search_menu": "Serĉu konektilojn...", + "scenes.apps.tasks.no_connectors_menu_text": "Vi ne havas konektilojn, kiuj povas konektiĝi al kalendaro.", + "scenes.apps.tasks.unconfigured_tab": "Ĉi tiu langeto ankoraŭ ne estas agordita.", + "scenes.apps.tasks.choose_board_button": "Elektu tabulon", + "scenes.apps.tasks.new_board.title": "Nova tabulo", + "scenes.apps.tasks.new_board.edit_title": "Redakti tabulon", + "scenes.apps.tasks.no_tasks": "Neniu tasko", + "scenes.apps.tasks.task_status.todo": "Farendaĵo", + "scenes.apps.tasks.task_status.current": "Aktuala", + "scenes.apps.tasks.task_status.done": "Farita", + "scenes.apps.tasks.task.description": "Priskribo", + "scenes.apps.tasks.task.assignees": "Asignitoj", + "scenes.apps.tasks.task.edit.dates": "Datoj", + "scenes.apps.tasks.list_modal.modify_list": "Modifi liston", + "scenes.apps.tasks.list_modal.new_list": "Nova listo", + "scenes.apps.tasks.list_modal.remove": "Forigi liston kaj taskojn", + "scenes.apps.tasks.list_modal.predefined_participants": "Antaŭdifinitaj partoprenantoj", + "scenes.apps.tasks.list_modal.archive_all_tasks": "Arkivu ĉiujn taskojn", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Forigi arkivitajn taskojn ({{$1}})", + "scenes.login.footer.go_to_twake": "Iru al twakeapp.com", + "scenes.login.footer.branding": "Vi estas sur {{$1}} ({{$2}}) privata Twake-servilo. ", + "scenes.login.create_account.title": "Kreu novan konton", + "scenes.login.create_account.email": "Retpoŝto", + "scenes.login.create_account.email_used": "Ĉi tiu retpoŝto jam estas uzata.", + "scenes.login.create_account.newsletter": "Ricevu informojn pri Twake", + "scenes.login.create_account.lastname": "Familia nomo", + "scenes.login.forgot_password.title": "Ĉu vi forgesis la pasvorton?", + "scenes.login.forgot_password.text": "Vi ricevos 9-ciferan kodon retpoŝte por kontroli vian identecon.", + "scenes.login.forgot_password.email_to_recover": "Retpoŝto por reakiri", + "scenes.login.forgot_password.mail_doesnt_exist": "Ĉi tiu retpoŝto ne ekzistas", + "scenes.login.forgot_password.text2": "Vi ricevos 9-ciferan kodon. Bonvolu enigi ĝin en la suban kampon por daŭrigi.", + "scenes.login.forgot_password.invalid_code": "Ĉi tiu kodo ne validas.", + "scenes.login.home.unable_to_connect": "Nevalida akreditaĵojn", + "scenes.login.home.password": "Pasvorto", + "scenes.login.home.login_btn": "Ensaluti", + "scenes.login.home.lost_password": "Ĉu vi forgesis la pasvorton?", + "scenes.login.home.create_account": "Krei konton", + "scenes.login.create_account.password": "Pasvorto", + "scenes.login.create_account.step_1_subtitle": "Ĝi ne povus esti pli simpla — ni nur bezonas iom da informoj.", + "scenes.login.create_account.step_2_subtitle_a": "Aldonu vian plenan nomon por ke aliaj uzantoj rekonu vin.", + "scenes.app.workspaces.create_company.company_name.placeholder": "Nomo de Firmo", + "scenes.app.workspaces.create_company.company_name.title_1": "Komenci,", + "scenes.app.workspaces.create_company.company_name.title_2": "indiku la nomon de via kompanio.", + "scenes.app.workspaces.create_company.default_workspace_name": "Ĉeflaborejo", + "scenes.app.workspaces.create_company.group_data.title": "Ni rapidos — ni bezonas nur kelkajn statistikajn informojn.", + "scenes.app.workspaces.create_company.importations.title_1": "Ĉu vi jam laboras kun ciferecaj iloj? Importu aŭ integru viajn ilojn nun!", + "scenes.app.workspaces.create_company.importations.title_2": "Ne zorgu, vi povas fari tion poste!", + "scenes.app.workspaces.create_company.invitations.title_2": "Aldonu uzantojn al via teamo.", + "scenes.app.workspaces.create_company.title": "Kreu mian kompanion", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "Aldonu sekundaran retpoŝton", + "scenes.app.workspaces.welcome_page.added_to_company": "Vi estis invitita al ", + "scenes.app.workspaces.welcome_page.create_my_company": "Kreu mian kompanion", + "scenes.app.workspaces.welcome_page.lets_go": "Ni iru!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Ĉu vi estis invitita uzante alian retadreson?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Ho, nu... Ŝajnas, ke neniu ankoraŭ invitis vin al firmao.", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Neniu ankoraŭ invitis vin al laborspaco.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Vi estas preta labori nun.", + "scenes.app.workspaces.welcome_page.see_you_soon": "Ĝis baldaŭ!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Vi povas ligi plurajn retadresojn al via konto; nur unu adreso estos uzata por sendi al vi sciigojn.", + "scenes.app.workspaces.welcome_page.main_mail_title": "Ĉefa adreso", + "scenes.app.workspaces.welcome_page.add_new_email": "Aldonu retmesaĝon", + "scenes.app.workspaces.welcome_page.code_verification": "Konfirmkodo", + "scenes.app.workspaces.welcome_page.new_email": "Aldonu duaran retpoŝton", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Ni sendis al vi konfirmkodon per {{$1}}", + "scenes.app.workspaces.welcome_page.done": "Mi finis", + "scenes.login.forgot_password.finished": "Via pasvorto estis sukcese ĝisdatigita.", + "scenes.apps.account.account.description_main": "Via ĉefa adreso estas kie Twake sendas viajn sciigojn. Viaj malĉefaj adresoj permesas vin aŭtomate inviti al la laborspacoj, kiuj uzas ilin.", + "scenes.apps.account.account.emails.description": "Administru viajn malsamajn retadresojn.", + "scenes.apps.account.account.make_main": "Agordu ĉefa", + "scenes.apps.account.account.password.description": "Ŝanĝu vian pasvorton.", + "scenes.apps.account.identity": "Identeco", + "scenes.apps.account.identity.description": "Ŝanĝu vian antaŭnomon, familian nomon kaj profilbildon videblan por aliaj uzantoj de Twake.", + "scenes.apps.account.preference": "Agordoj", + "general.open": "Malfermi", + "scenes.apps.account.thumbnail.max_weight": "Maksimuma grandeco 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "Konfirmu ĉi tiun retmesaĝon", + "app.name.twake_calendar": "Kalendaro", + "app.name.twake_drive": "Dokumentoj", + "app.name.twake_tasks": "Taskoj", + "components.calendar.repetition.repeat": "Ripetu ĉiun", + "components.calendar.repetition.ends": "Finiĝas", + "components.calendar.repetition.never": "Neniam", + "components.calendar.repetition.days": "tago(j)", + "components.calendar.repetition.weeks": "semajno(j)", + "components.calendar.repetition.months": "monato(j)", + "components.calendar.repetition.years": "jaro(j)", + "components.calendar.repetition.custom_recurrence": "Propra ripetiĝo", + "components.calendar.repetition.occurrence": "Okazo(j)", + "components.calendar.repetition.repeat_on": "Ripeti plu", + "scenes.app.channelsbar.currentuser.add_apps": "Serĉu aplikojn", + "scenes.app.channelsbar.currentuser.change_my_status": "Ŝanĝu mian statuson", + "scenes.app.channelsbar.currentuser.collaborateurs": "Uzantoj", + "scenes.app.channelsbar.currentuser.workspace_info": "Vi estas en la laborspaco {{$1}} de la grupo {{$2}}", + "scenes.app.channelsbar.currentuser.logout": "Adiaŭi", + "scenes.app.channelsbar.currentuser.update": "Ĝisdatigi", + "scenes.app.channelsbar.currentuser.disable_notifications": "Malebligu", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Malebligu dum 1 h", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Malebligu ĝis 9 a.m. morgaŭ", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Reaktivigi", + "scenes.app.channelsbar.currentuser.user_parameter": "Sciigaj agordoj", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Numero de mesaĝoj", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "En la senpaga versio de Twake, vi ne povas aliri pli ol {{$1}} lastatempajn mesaĝojn.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Montru pliajn planojn", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "Nova privata diskuto", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Neniuj privataj mesaĝoj. Invitu uzantojn!", + "scenes.app.channelsbar.channelsuser.private_messages": "Rektaj mesaĝoj", + "scenes.app.channelsbar.channelsworkspace.channel_title": "KANALOJ", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "PREFERATOJ", + "scenes.app.channelsbar.channelsworkspace.create_channel": "Kreu kanalon", + "scenes.app.channelsbar.channelsworkspace.no_channel": "Vi ankoraŭ ne aliĝis al iu ajn kanalo", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Vi povas importi ĉi tiujn kanalojn en vian komercon por resti organizita klakante sur ĉi tiu kadro.", + "scenes.app.channelsbar.company_invitation_alert_title": "Vi estas invitita al la kompanio ", + "scenes.app.channelsbar.initial_instructions_tutorial": "Elektu antaŭnomon, nomon kaj profilbildon.", + "scenes.app.channelsbar.installation_desktop_tutorial": "Instalu la labortablan aplikaĵon", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Invitu uzantojn en vian laborspacon.", + "scenes.app.channelsbar.public_channel_label": "Publika", + "scenes.app.channelsbar.private_channel_label": "Privata", + "scenes.app.channelsbar.sending_message_instruction": "Sendu vian unuan mesaĝon en diskuto", + "scenes.app.channelsbar.tutorial_alert": "Ĉu vi neniam plu montri ĉi tiun kadron?", + "scenes.app.channelsbar.welcome": "Bonvenon al Twake", + "scenes.app.channelsbar.welcoming_message_subtitle": "Fariĝu Twake-profesiulo per nur kelkaj klakoj!", + "scenes.app.mainview.instruction_current_tab": "Komencu elektante kanalon maldekstre.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Vi ne havas konektilon, kiu povas konektiĝi al kanalo.", + "scenes.app.mainview.tabs.rename": "Ŝanĝi nomon", + "scenes.app.mainview.tabs.searching_connectors": "Serĉu konektilojn...", + "scenes.app.popup.adduser.adresses_message": "Bonvolu apartigi la adresojn per komo aŭ spaco. Memoru, ke Twake povas limigi la nombron da invitoj laŭ via abono.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Invita ligo al la laborspaco", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Nova ligilo generita", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Sukcese kopiita al tondujo", + "scenes.app.popup.adduser.magiclinks.action_copy": "Kopii", + "scenes.app.popup.adduser.magiclinks.action_generate": "Generi", + "scenes.app.popup.appsparameters.pages._app_identity": "Identeco de la aplikaĵo", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Testu la aspekton de viaj Twacode-mesaĝoj", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Via kandidatiĝo estas publikigita, vi ne povas redakti ĝin.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Uzu * en evoluo por permesi ĉiujn IP-adresojn.", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "Mia mirinda apo", + "scenes.app.popup.appsparameters.pages.api_data_description": "Utilaj datumoj por la Twake API.", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "API-agordoj", + "scenes.app.popup.appsparameters.pages.app_name_label": "Nomo de la aplikaĵo", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Ĉiuj administrantoj de ĉi tiu kompanio povos redakti ĉi tiun aplikaĵon.", + "scenes.app.popup.appsparameters.pages.apps_title": "Viaj aplikoj kaj konektiloj", + "scenes.app.popup.appsparameters.pages.automatique_label": "Aŭtomata", + "scenes.app.popup.appsparameters.pages.button_force": "Forto tra la kompanio", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "Okazaĵo de tipo '{{$1}}' kaj id '{{$2}}' kun pasivoj '{{$3}}'", + "scenes.app.popup.appsparameters.pages.company_label": "Kompanio posedanto", + "scenes.app.popup.appsparameters.pages.configuration_label": "Agordo", + "scenes.app.popup.appsparameters.pages.create_app_button": "Krei aplikaĵon", + "scenes.app.popup.appsparameters.pages.create_my_app": "Kreu mian aplikaĵon", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Vi ankoraŭ ne kreis apon. Antaŭ ol vi kreas aplikaĵon aŭ konektilon, certigu, ke ĝi ne jam ekzistas en nia aplikaĵa merkato.", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "Forigi aplikaĵon", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "Danĝera zono", + "scenes.app.popup.appsparameters.pages.description_label": "Priskribo", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Aplikoj evoluigitaj de la kompanio", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Permesas al vi difini kie via aplikaĵo estos videbla.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Montraj agordoj", + "scenes.app.popup.appsparameters.pages.error_check_needed": "Eraro okazis; kontrolu viajn informojn.", + "scenes.app.popup.appsparameters.pages.error_message": "Tiu ĉi nomo jam estas uzata de alia aplikaĵo; bonvolu elekti alian.", + "scenes.app.popup.appsparameters.pages.error_user_code": "eraro", + "scenes.app.popup.appsparameters.pages.event_subtitle": "Eventoj", + "scenes.app.popup.appsparameters.pages.filter_information": "Ĉi tiu filtrilo limigas la uzon de via API-ŝlosilo nur al serviloj en via konektilo.", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Ĉi tiu nomo jam estas uzata de alia aplikaĵo. Bonvolu elekti alian.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Simpligita nomo", + "scenes.app.popup.appsparameters.pages.installation": "Instali.", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Pasivaj datumoj, kiuj estos senditaj en la venonta Evento", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Redaktu la publikajn datumojn de via aplikaĵo.", + "scenes.app.popup.appsparameters.pages.new_app_title": "Nova aplikaĵo", + "scenes.app.popup.appsparameters.pages.ok_user_code": "bone", + "scenes.app.popup.appsparameters.pages.optimal_format": "Optimuma formato: 48x48px.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "La neeldonita aplikaĵo funkcios nur en via kompanio. Se vi volas disponigi ĝin al ĉiuj uzantoj de Twake, aktivigu ĉi tiun opcion.", + "scenes.app.popup.appsparameters.pages.public_availability_application": "Publika aplikado", + "scenes.app.popup.appsparameters.pages.public_login_label": "Publika identigilo", + "scenes.app.popup.appsparameters.pages.publication_label": "Publikigo", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Eldoni aplikaĵon", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Legu privilegiojn", + "scenes.app.popup.appsparameters.pages.remove_app": "Forigu la aplikaĵon {{$1}} konstante.", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Forigu de la tuta kompanio", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Forigi el laborspaco", + "scenes.app.popup.appsparameters.pages.show_button": "Montri", + "scenes.app.popup.appsparameters.pages.status_tilte": "Stato", + "scenes.app.popup.appsparameters.pages.string_information": "Ĉi tiu ĉeno identigas vian aplikaĵon kaj estos uzata en mesaĝaj komandoj.", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode-testilo", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "Url de evento-ricevo", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "Atendante…", + "scenes.app.popup.appsparameters.pages.website_label": "Retejo", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Skribu privilegiojn", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Vi ne povas forigi ĉi tiun apon se ĝi estas publikigita.", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "La simpligita nomo de via aplikaĵo jam estas uzata de alia aplikaĵo. Bonvolu ŝanĝi ĝin.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Okazis eraro dum la ĝisdatigo de la aplikaĵo.", + "scenes.app.popup.appsparameters.pages.remove_app_button": "Forigi aplikaĵon", + "scenes.app.popup.appsparameters.pages.update_button": "Ĝisdatigi", + "scenes.app.popup.createworkspacepage.add_subtitle": "Ĉu vi bezonas pli da spaco?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Kreu novan laborspacon", + "scenes.app.popup.createworkspacepage.placeholder_name": "Nomo de la laborspaco", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Agordu la oftecon de moveblaj sciigoj.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Ofteco de sciigoj", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Emfazu la sekvajn ŝlosilvortojn:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Agordu la oftecon de retpoŝtaj sciigoj.", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Montri enhavon pri privataj mesaĝoj", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Elektu periodon dum kiu vi ne ricevas sciigojn.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Ne ĝenu nokte", + "scenes.app.popup.userparameter.pages.notif_content_label": "Enhavo de sciigoj", + "scenes.app.popup.workspaceparameter.admin_current_status": "Vi estas Administranto.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Vi estas administranto de laborspaco.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Vi estas administranto de la kompanio.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Forigi laborspacon", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Vi devas esti sola en la laborspaco por forigi ĝin. Forigu viajn kunlaborantojn kaj provu denove.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Forigo de laborspaco ne povas esti malfarita. Ĉiuj mesaĝoj kaj dosieroj estos nereveneblaj.", + "scenes.app.popup.workspaceparameter.pages.enter": "Eniru ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Aliru viajn aplikaĵojn kaj konektilojn", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Moderiganto de laborspaco", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Vi ne povas forlasi la laborspacon, ĉar vi estas la lasta administranto. Vi povas difini novan administranton aŭ forigi/arkivi ĉi tiun laborspacon.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Ĉiuj aplikoj", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Aplikoj de via kompanio", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Integriĝoj", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Serĉu aplikojn", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Aplikoj de ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Invitu uzantojn", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Uzantoj", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Aplikoj evoluigitaj de la kompanio", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Identeco de la kompanio", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Ŝanĝu la nomon de ĉi tiu kompanio", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "Nomo de la kompanio", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "agordo", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Agordoj ", + "scenes.app.popup.workspaceparameter.pages.description": "Priskribo", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Aplikoj evoluigitaj de la kompanio", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Instalu la aplikaĵon en ĉi tiu laborspaco.", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Aplikoj instalitaj en ĉi tiu laborspaco {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Aplikoj instalitaj en aliaj areoj de la kompanio {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Instalitaj aplikaĵoj", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Okazis eraro dum invitado de la sekvaj uzantoj: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Kontrolu, ke la uzantnomo aŭ retpoŝto uzata estas valida.", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Redaktu la bildon de ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Emblemo", + "scenes.app.popup.workspaceparameter.pages.name_description": "Ŝanĝu la nomon de ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.name_label": "Nomo de la laborspaco", + "scenes.app.popup.workspaceparameter.pages.no_access": "Neniu aliro.", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "Vi ne havas aplikojn en ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Forlasu ĉi tiun laborspacon", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Lega aliro", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Forigu de la tuta kompanio", + "scenes.app.popup.workspaceparameter.pages.research_by": "Serĉu aplikojn laŭ nomo kaj kategorioj", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Serĉu aplikaĵojn...", + "scenes.app.popup.workspaceparameter.pages.show_button": "Montru", + "scenes.app.popup.workspaceparameter.pages.title": "Agordoj de laborspaco", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Aliro al rethokoj", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Maksimuma grandeco 5 MB.", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Forigu el ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "laborejo", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Skriba aliro", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Viaj aplikoj", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Pagoj kaj abonoj", + "scenes.app.workspacesbar.components.change_company_title": "Ŝanĝi firmaon", + "scenes.app.workspacesbar.components.create_company_menu": "Kreu kompanion", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} agordoj", + "scenes.apps.calendar.add_calendar_menu": "Aldonu kalendaron", + "scenes.apps.calendar.connectors_menu": "Konektiloj…", + "scenes.apps.calendar.connectors_search_menu": "Serĉu konektilojn...", + "scenes.apps.calendar.create_calendar_title": "Kreu kalendaron", + "scenes.apps.calendar.day_option": "Tago", + "scenes.apps.calendar.edit_calendar_title": "Redaktu la kalendaron", + "scenes.apps.calendar.export_title": "Elporti", + "scenes.apps.calendar.export_view_menu": "Eksportu la vidon...", + "scenes.apps.calendar.ics_download_menu": "Elŝutu ICS-dosieron", + "scenes.apps.calendar.ics_subscription_menu": "Akiru ICS-abonligon", + "scenes.apps.calendar.modals.advanced_options": "Altnivelaj opcioj", + "scenes.apps.calendar.modals.description_placeholder": "Priskribo", + "scenes.apps.calendar.modals.details_title": "Detaloj", + "scenes.apps.calendar.modals.event_adresse_placeholder": "Adreso", + "scenes.apps.calendar.modals.event_description_placeholder": "Priskribo", + "scenes.apps.calendar.modals.event_title_placeholder": "Titolo", + "scenes.apps.calendar.modals.modify_event_button": "Redaktu eventon", + "scenes.apps.calendar.modals.part.participants": "Partoprenantoj", + "scenes.apps.calendar.modals.participants_event": "Partoprenantoj", + "scenes.apps.calendar.modals.reminders": "Rememorigiloj", + "scenes.apps.calendar.modals.remove_button": "Forviŝi", + "scenes.apps.calendar.modals.remove_event_button": "Forigi eventon", + "scenes.apps.calendar.modals.remove_event_text": "Ĉu forigi la eventon?", + "scenes.apps.calendar.modals.title_placeholder": "Titolo", + "scenes.apps.calendar.modify_calendar_menu": "Redaktu la kalendaron", + "scenes.apps.calendar.month_option": "Monato", + "scenes.apps.calendar.my_calendar": "Mia kalendaro", + "scenes.apps.calendar.my_calendar_label": "Mia kalendaro", + "scenes.apps.calendar.week_option": "Semajno", + "scenes.apps.calendar.workspace": "Laborejo", + "scenes.apps.calendar.my_calendar_menu": "Mia kalendaro", + "scenes.apps.calendar.no_calendar_text": "Vi ne agordis iujn ajn kalendarojn por ĉi tiu laborspaco.", + "scenes.apps.calendar.no_connectors_menu_text": "Vi ne havas konektilojn, kiuj povas konektiĝi al kalendaro.", + "scenes.apps.calendar.remove_calendar_confirmation": "Ĉu forigi la kalendaron kaj ĝiajn eventojn konstante?", + "scenes.apps.calendar.today_menu": "Hodiaŭ", + "scenes.apps.calendar.workspace_label": "Ĉi tiu laborspaco", + "scenes.apps.calendar.workspace_menu": "Laborejo", + "scenes.apps.drive.add_button": "Aldoni", + "scenes.apps.drive.message_added_file": "{{$1}} sendis {{$2}}.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} sendis plurajn dosierojn.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} sendis dosieron.", + "scenes.apps.drive.choose_folder_button": "Elektu dosierujon", + "scenes.apps.drive.choose_file_button": "Elektu dosieron", + "scenes.apps.drive.create_folder_button": "Krei", + "scenes.apps.drive.go_trash_menu": "Iru al rubujo", + "scenes.apps.drive.import_from_computer_menu": "Alŝutu de komputilo", + "scenes.apps.drive.move_text": "Movi", + "scenes.apps.drive.new_file_menu": "Nova dosiero", + "scenes.apps.drive.download_button": "Elŝuti", + "scenes.apps.drive.open_link": "Malfermu ligilon en nova fenestro", + "scenes.apps.drive.files_subtitle": "Dosieroj", + "scenes.apps.drive.folder_subtitle": "Dosierujoj", + "scenes.apps.drive.go_out_trash_menu": "Lasu rubon", + "scenes.apps.drive.new_file_title": "Nova dosiero", + "scenes.apps.drive.new_external_storage": "Nova ekstera stokado", + "scenes.apps.drive.no_file_alert": "Vi ne havas aplikaĵojn, kiuj permesas krei dosieron.", + "scenes.apps.drive.no_storage_app_alert": "Vi ne havas aplikojn, kiuj permesas vin aldoni eksteran stokadon.", + "scenes.apps.drive.new_folder_title": "Nova dosierujo", + "scenes.apps.drive.remove_definitely_menu": "Forigu konstante", + "scenes.apps.drive.restore_menu": "Restaŭri", + "scenes.apps.drive.throw_menu": "Sendu al la rubujo", + "scenes.apps.drive.trash_empty_menu": "Malplenigu la rubon", + "scenes.apps.drive.unconfigured_tab": "Ĉi tiu langeto ankoraŭ ne estas agordita.", + "scenes.apps.drive.viewer.edit_with_button": "Redaktu per {{$1}}", + "scenes.apps.drive.viewer.loading_preview_message": "Ŝargante…", + "scenes.apps.drive.viewer.no_preview_message": "Ne povas vidi tian dosieron.", + "scenes.apps.drive.viewer.open_with_button": "Malfermu kun...", + "scenes.apps.messages.input.placeholder": "Skribu mesaĝon. Uzu @ por citi uzanton.", + "scenes.apps.messages.input.edited": "Redaktita", + "scenes.apps.messages.just_you": "Videbla nur por vi", + "scenes.apps.messages.message.new_messages_bar": "Novaj mesaĝoj", + "scenes.apps.messages.message.cancel_button": "Nuligi", + "scenes.apps.messages.message.modify_button": "Modifi", + "scenes.apps.messages.message.pin_button": "Pin mesaĝo", + "scenes.apps.messages.message.unpin_button": "Malfiksi mesaĝon", + "scenes.apps.messages.message.copy_link": "Kopiu ligilon al mesaĝo", + "scenes.apps.messages.message.pinned": "Alpinglita", + "scenes.apps.messages.message.remove_button": "Forviŝi", + "scenes.apps.messages.message.types.first_message_text": "Ĉi tiu estas la unua mesaĝo", + "scenes.apps.messages.message.types.no_message_in_thread": "Neniu ankoraŭ respondis.", + "scenes.apps.messages.messageslist.get_writing_user": "skribas...", + "scenes.apps.messages.messageslist.get_writing_users": "skribas...", + "scenes.apps.messages.messageslist.go_last_message_button": "Iru al la lasta mesaĝo", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Novaj mesaĝoj", + "scenes.error_on_twake": "\"Houston ni havas problemon\"", + "scenes.help_us": "Tamen, se vi ŝatus helpi nin ripari ĉi tiun eraron, sendu al ni mesaĝon sube: ", + "scenes.login.verifymail.alert": "Ni kontrolas vian retpoŝton!", + "scenes.login.verifymail.verification_waiting": "Atendante konfirmon...", + "scenes.no_panic": "Ne paniku! Nur reŝargi ĉi tiun paĝon por ripari Twake.", + "services.apps.calendar.deadline_icon": "Limdato", + "services.apps.calendar.event_icon": "Evento", + "services.apps.calendar.move_icon": "Movi", + "services.apps.calendar.reminder_icon": "Rememorigilo", + "services.apps.messages.no_app": "Ĉi tiu aplikaĵo ne ekzistas.", + "services.apps.messages.no_command_possible": "Ni ne povas ekzekuti la komandon '{{$1}}' ĉar '{{$2}}' ne ekzistas aŭ ne permesas krei komandojn.", + "scenes.apps.drive.top_menu_more": "Pli", + "scenes.apps.drive.top_menu_no_items": "{{$1}} eroj", + "scenes.apps.messages.new_thread": "Komencu novan diskuton", + "scenes.apps.messages.input.send_message": "Sendi mesaĝon", + "services.user.notification_parameters_update_alert": "La sciigaj agordoj estis ĝisdatigitaj.", + "services.user.update_password_alert": "Via pasvorto estas ĝisdatigita.", + "'": "'", + "\"": "\"", + "login.create_account": "Krei konton", + "login.login_error": "Eraro dum ensaluto", + "scenes.app.workspaces.components.skip": "Saltu", + "scenes.apps.calendar.unconfigured_tab": "Ĉi tiu langeto ankoraŭ ne estas agordita.", + "scenes.apps.drive.trash": "Rubujo", + "scenes.apps.messages.input.emoji": "Mienvinjetoj", + "scenes.apps.messages.input.hide_formatting": "Kaŝi formatadon", + "scenes.apps.messages.input.show_formatting": "Montru formatadon", + "scenes.tell_us": "Bonvolu diri al ni, kion vi faris ĉe:", + "scenes.apps.drive.viewer.download_desktop": "Elŝutu Twake Desktop por antaŭrigardi en la programo", + "scenes.apps.tasks.my_tasks": "Miaj taskoj", + "scenes.apps.tasks.board.tasks.use_starttime": "Uzu komencan tempon", + "scenes.apps.tasks.board.tasks.in_list": "En listo", + "scenes.apps.tasks.board.starts": "Komencas la", + "scenes.apps.tasks.board.ends": "Farenda por la", + "scenes.apps.tasks.board.list_name": "Listo nomo", + "scenes.app.popup.sync_calendar": "Sinkronigu viajn kalendarojn.", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "Logo de la firmao", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "Redakti firmaobildon ", + "scenes.apps.account.account.save": "Konservu konton", + "scenes.apps.account.message_temporary": "Provizora konto funkcias kiel normala Twake-konto, sed vi kreas la pasvorton kaj vi povos rekomencigi ĝin se necese.", + "scenes.apps.account.message_user_signin": "Via uzanto povas ensaluti iam ajn uzante ĉi tiun saman retpoŝton kaj ŝanĝi la provizoran konton al normala konto.", + "scenes.app.mainview.link_expired": "Ĉi tiu publika ligo estas nevalida aŭ eksvalidiĝis.", + "scenes.app.mainview.create_account": "Kreu vian laborspacon senpage ", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "Nuligi la inviton", + "scenes.apps.account.account.fullname": "Plena nomo", + "login.email_login": "Retpoŝto / Ensalutu", + "scenes.apps.account.account.password_for_user": "Pasvorto por via uzanto", + "scenes.apps.account.account.send_info": "Sendu ĉi tiujn akreditaĵojn al via uzanto.", + "scenes.apps.calendar.modals.reminder_add": "Aldonu memorigilon", + "scenes.apps.parameters.workspace_sections.members.invite_all": "Invitu ĉiujn", + "scenes.app.taskpicker.select": "Elekti", + "components.listmanager.filter": "Filtri", + "scenes.apps.tasks.no_connector": "Neniu konektilo", + "components.attachmentpicker.add_attachment": "Aldonu aldonaĵojn", + "components.drive.right_preview.suppress_link": "Subpremi la ligilon", + "components.drive.right_preview.create_link": "Kreu alirligilon", + "components.drive.moove_here": "Movu ĉi tien", + "components.drive.modify_uslist": "Modifi uzantliston", + "components.tagpicker.tag_name": "Etikedo nomo", + "components.workspace.list_manager.no_workspace": "Neniu laborspaco", + "components.workspace.list_manager.add": "Aldonu laborspacojn", + "components.workspace.list_manager.current_space": "Nuna laborspaco", + "components.workspace.list_manager.current_company": "Nuna firmao", + "components.workspace.list_manager.all": "Ĉiuj", + "components.workspace.calendar.invalid": "Nevalida", + "components.searchpopup.enter_text": "Enigu iun tekston por serĉi Twake.", + "components.searchpopup.loading": "Ŝargante pliajn rezultojn", + "components.searchpopup.filter_ws": "Filtri la laborspacojn", + "components.searchpopup.tags": "Etikedoj", + "components.searchpopup.size": "Grando", + "components.searchpopup.creation": "Kreado", + "components.searchpopup.update_search": "Ĝisdatigu serĉon", + "components.searchpopup.last_modif": "Lasta modifo", + "components.searchpopup.sender": "Sendinto", + "components.searchpopup.mentions": "Mencioj", + "scenes.apps.board.archived_tasks": "Arkivitaj taskoj ({{$1}})", + "scenes.apps.board.active_tasks": "Aktivaj taskoj", + "components.searchpopup.only_pinned": "Nur alpinglitaj mesaĝoj", + "components.alert.confirm": "Konfirmu vian agon", + "components.alert.confirm_click": "Konfirmu vian agon alklakante OK.", + "components.searchpopup.tasks": "Taskoj", + "scenes.app.mainview.advanced_search_placeholder": "Altnivela serĉo", + "components.searchpopup.hide_filters": "kaŝi filtrilojn", + "components.searchpopup.show_filters": "montri filtrilojn", + "components.searchpopup.load_more": "Ŝarĝu pli da rezultoj", + "general.more": "Pli", + "scenes.apps.board.kanban": "Kanban", + "scenes.apps.board.display_as": "Montru kiel", + "scenes.apps.board.new_task": "+ Nova tasko", + "scenes.apps.board.all_boards": "Ĉiuj Estraroj", + "components.reminder.by_email": "Retpoŝto", + "components.userlistmanager.no_users": "Neniuj uzantoj.", + "scenes.apps.drive.used": "uzata en ĉi tiu dosierujo", + "components.reminder.notification": "Sciigo", + "components.reminder.minutes_bef": "minutojn antaŭe", + "components.reminder.hours_bef": "horojn antaŭe", + "components.reminder.days_bef": "tagojn antaŭe", + "components.reminder.weeks_bef": "semajnoj antaŭe", + "scenes.apps.calendar.reminders": "memorigilo(j)", + "scenes.apps.calendar.video_link": "Klaku por malfermi ligilon", + "scenes.app.mainview.discussion": "Diskuto", + "components.tagpicker.notag": "Neniu etikedo", + "scenes.apps.tasks.modals.attachments": "Aldonaĵoj", + "components.calendar.calendarselector.from": "De", + "scenes.apps.drive.move_text2": "Movi", + "components.attachmentpicker.from_computer": "De via aparato", + "components.attachmentpicker.from_twake": "De Twake Dokumentoj", + "components.attachmentpicker.file": "Dosiero", + "components.attachmentpicker.remove_attach": "Forigi aldonaĵon", + "scenes.apps.drive.remove_attachs": "Forigi aldonaĵojn", + "components.drive.elements.see": "Vidu", + "components.drive.elements.current_name": "Nuna nomo: ", + "scenes.apps.drive.right_preview.public": "Publika aliro", + "components.drive.elements.configurate_mod": "Agordi la modon...", + "components.drive.elements.manage_version": "Administri versiojn", + "scenes.app.popup.createcompany.try_again": "Bonvolu reprovi.", + "scenes.app.popup.workspace.edit_temp": "Redaktu provizoran konton", + "scenes.app.popup.workspace.create_temp": "Krei provizoran konton", + "scenes.apps.tasks.active_tasks": "aktivaj taskoj", + "scenes.apps.drive.right_preview.versions": "Versioj", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Administru viajn aplikojn kaj konektilojn.", + "scenes.app.popup.appsparameters.pages.icon": "Piktogramo", + "scenes.app.popup.appsparameters.pages.title_informations": "Bazaj informoj", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Informoj rilataj al aplika administrado", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Nuna uzantidentigilo", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Nuna laborspaca id", + "scenes.client.channelbar.channelmemberslist.loader": "Ŝarĝu pli", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Serĉu uzantojn", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Forigi el kanalo", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Kreu kanalon", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Nuna grupid", + "scenes.app.mainview.channel_description": "Priskribu la kanalon", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Aŭtomate invitu ĉiujn uzantojn de laborspaco al ĉi tiu kanalo", + "scenes.client.channelbar.channelmemberslist.title": "Uzantoj en {{$1}}", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Aliĝu al kanalo", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Serĉu kanalon, uzanton aŭ rektajn mesaĝojn", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Kreu novan langeton", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "Alinomigi {{$1}}", + "components.connectorslistmanager.add_connectors": "Aldonu konektilojn", + "components.notifications.hidden_notifications_button.children": "Novaj mesaĝoj", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "Programo", + "scenes.client.channelbar.channelmemberslist.no_members": "Ne estas uzanto en ĉi tiu kanalo, vi povas inviti ilin alklakante Aldoni uzantojn.", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Kaŝi diskuton", + "components.inputs.input_with_select.input.placeholder": "Kanala nomo", + "components.inputs.input_with_select.select.placeholder": "Nomo de sekcio", + "components.inputs.input_with_select.select.no_sections": "Vi povas grupigi viajn kanalojn ĉi tie", + "components.inputs.input_with_select.button.tooltip": "Agordu kanalan sekcion", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} aldonis {{$2}} al la kanalo", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} forigis {{$2}} de la kanalo", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} ŝanĝis la priskribon", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} renomis la kanalon al {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} forigis konektilon {{$2}}", + "components.alert.leave_private_channel.description": "Vi ne povos denove aliĝi al ĉi tiu privata kanalo krom se iu invitas vin.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Vi ne estas membro", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Ŝarĝu pli", + "general.re_send": "Resendi", + "general.verify": "Kontrolu", + "scenes.client.channelbar.channelmemberslist.tag": "Vi", + "components.alert.leave_private_channel.title": "Ĉu vi certas, ke vi volas forlasi la kanalon?", + "components.unverified_account.typography_text_danger": "Bonvolu kontroli vian konton ene de {{$1}} tagoj. Se ne, via konto estos blokita post 7 tagoj kaj konstante forigita post 30 tagoj. Vi povas kontroli vian konton per la konfirma retpoŝto.", + "components.unverified_account.verification_details": "Ni sendis konfirman retpoŝton al", + "components.account_verication_status_unverified": "Nekontrolita", + "components.account_verication_status_blocked": "Ŝlosita", + "components.unverified_account.re_send_email": "Ĉu ne ricevis la retmesaĝon?", + "components.blocked_account.trial_period_over": "Via provperiodo finiĝis. Por malŝlosi vian konton kaj akiri aliron al ĉiuj funkcioj, bonvolu kontroli vian konton per retpoŝta konfirmo", + "components.add_mails_workspace.button": "Komencu uzi Twake", + "components.add_mails_workspace.title_1": "Aldonu kelkajn uzantojn", + "components.add_mails_workspace.title_2": "Twake estas teama kunlabora ilo, do invitu kelkajn uzantojn testi laborspacon, kiun ni kreis por vi.", + "components.add_mails_workspace.text_area_placeholder": "Enigu retpoŝtojn de viaj uzantoj*", + "components.verify_mail.title_1": "Gratulon", + "components.verify_mail.title_2": "Vi estas oficiala Twake-uzanto nun!", + "components.verify_mail.button": "Aldonu uzanton", + "components.verify_mail.text": "Antaŭ ĉio, vi devas kontroli vian retadreson. Ni sendis konfirman ligon al", + "components.verify_mail.paragraph": "Vi povas fari ĝin poste, se vi volas, sed nekontrolitaj kontoj havas aliron al nur limigita versio de Twake", + "services.console_services.toaster.add_emails_error": "Eraro dum aldono de retpoŝto(j)", + "services.console_services.toaster.add_email_error_message": "Eraro dum aldono de {{$1}}", + "services.console_services.toaster.success_verify_email": "Konfirma ligilo estis sendita al via retpoŝta konto", + "scenes.app.popup.workspaceparameter.edit_from_console": "Vidu en Konzolo", + "services.console_services.toaster.success_invite_emails": "Sukcese aldonis {{$1}} uzanto(j)", + "scenes.client.channels_bar.modals.guest_management.title": "Administri gastojn en {{$1}}", + "scenes.client.channels_bar.modals.guest_management.tips": "Komencu aldoni aŭ serĉi retpoŝton per la enigo supre", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Poŝto sendita", + "general.user.role.company.admin": "Administranto de la kompanio", + "general.user.role.company.member": "Membro", + "general.user.role.company.guest": "Gasto", + "components.richtexteditor.toolbar.strikethrough": "Trastreki", + "components.richtexteditor.toolbar.ordered-list": "Ordigita listo", + "components.richtexteditor.toolbar.blockquote": "Blokcitaĵo", + "components.richtexteditor.toolbar.code": "Kodo", + "components.richtexteditor.toolbar.unordered-list": "Kuglolisto", + "components.richtexteditor.toolbar.code-block": "Kodbloko", + "components.locked_features.locked_history_banner.title": "Vi ĵus atingis la mesaĝlimon", + "components.locked_features.locked_history_banner.description": "Via kompanio havas multajn mesaĝojn! Ĝisdatigu nun por aliri vian tutan mesaĝhistorion.", + "components.locked_features.locked_history_banner.button": "Lernu pli", + "components.locked_features.locked_guests_popup.title": "Gastoj funkcio estas ŝlosita", + "components.locked_features.locked_guests_popup.subtitle": "Ĉi tiu funkcio ne disponeblas en la senpaga versio de Twake", + "components.locked_features.locked_guests_popup.description": "Hus!! Ŝajnas, ke vi volas inviti eksterajn uzantojn al via laborejo. Vi eble volas konsideri ĝisdatigi vian planon se vi volas kunlabori kun gastoj kaj eksteraj partneroj. Esploru niajn prezajn elektojn kaj elektu la plej bonan eblon por viaj teamaj kunlaboraj bezonoj.", + "components.locked_features.locked_guests_popup.learn_more_button": "Lernu pli", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Saltu por Nun", + "components.locked_features.locked_guests_popup.or": "Aŭ", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Estas problemo kun via firmaa abono. Bonvolu rigardi vian", + "components.on_boarding.company_billing_banner.link": "abonplano de kompanio", + "components.on_boarding.popups.blocked_company.title": "Via firmao estas ŝlosita pro pagoproblemo", + "components.on_boarding.popups.blocked_company.description": "Via abono al Twake eksvalidiĝis. Bonvolu kontakti la posedanton aŭ administranton de via firmao por renovigi ĝin kaj povi komuniki kun via teamo denove!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Ĉu vi volas lerni pli pri firmaa abonplano?", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Klaku ĉi tie", + "components.on_boarding.popups.blocked_company.or": "Aŭ", + "components.on_boarding.popups.blocked_company.company_selector": "Ŝanĝu al alia kompanio", + "scenes.apps.tasks.select_user_button": "Rigardu taskojn por alia uzanto", + "scenes.apps.tasks.select_user": "Serĉu uzanton", + "scenes.apps.messages.input.attach_file.from_computer": "De komputilo", + "scenes.app.popup.workspaceparameter.pages.table_title": "Nomo", + "scenes.client.main_view.main_header.search_input": "Serĉi", + "scenes.apps.drive.new_link_title": "Nova ligilo", + "scenes.apps.drive.default_link_name": "Sentitola", + "components.emoji_picker.input_search_placeholder": "Serĉi", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Vi ne povas aldoni pli ol {{$2}} dosierojn en mesaĝo", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Vi forigis ĉi tiun mesaĝon", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} forigis sian mesaĝon", + "components.member.user_parts.and_more_user_text": " kaj {{$1}} pli da uzantoj", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Kreu privatan kanalon", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " anstataŭe", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Vi ne povas aldoni pli ol 10 uzantojn", + "components.upload.drop_files.toaster.error": "Vi ne povas alŝuti pli ol {{$1}} dosierojn", + "components.emoji_picker.categories.frequently_used": "Ofte Uzata", + "components.emoji_picker.categories.smileys_and_people": "Ridetonoj & Homoj", + "components.emoji_picker.categories.animals_and_nature": "Bestoj kaj Naturo", + "components.emoji_picker.categories.food_and_drink": "Manĝaĵo & Trinkaĵo", + "components.emoji_picker.categories.activity": "Aktivecoj", + "components.emoji_picker.categories.travel_and_places": "Vojaĝoj & Lokoj", + "components.emoji_picker.categories.objects": "Objektoj", + "components.emoji_picker.categories.symbols": "Simboloj", + "components.emoji_picker.categories.flags": "Flagoj", + "components.emoji_picker.categories.not_found": "Neniu Emoji Trovita", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Rolo", + "general.email": "Retpoŝto", + "components.locked_features.locked_workspace_popup.title": "Vi ne povas krei pliajn laborspacojn", + "components.locked_features.locked_workspace_popup.subtitle": "En la senpaga versio, vi povas havi nur unu laborspacon en via kompanio.", + "components.locked_features.locked_workspace_popup.text": "Hus!! Ĉu vi volas krei novan laborspacon en via kompanio? Vi eble volas konsideri ĝisdatigi vian planon. Esploru niajn prezajn elektojn kaj elektu la plej bonan elekton por viaj teamaj kunlaboraj bezonoj.", + "components.locked_features.locked_only_office_popup.title": "Vi ne povas redakti ĉi tiun dosieron", + "components.locked_features.locked_only_office_popup.text": "Hus!! Ŝajnas, ke vi volas redakti la dosieron de Twake. Vi eble volas konsideri ĝisdatigi vian planon se vi volas kunlabori ĉirkaŭ oficejaj dosieroj. Esploru niajn prezajn elektojn kaj elektu la plej bonan eblon por viaj teamaj kunlaboraj bezonoj.", + "components.locked_features.locked_drive_popup.subtitle": "En la senpaga versio, vi povas stoki nur 6GB.", + "general.pause": "Paŭzo", + "scenes.app.integrations_parameters.title": "Integriĝoj", + "scenes.app.integrations_parameters.applications_table.name": "Nomo", + "scenes.app.integrations_parameters.applications_table.title": "Aliaj integriĝoj", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Serĉu aplikaĵon", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Priskribo", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Retejo", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Montru", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Forigi el la kompanio", + "scenes.app.integrations_parameters.company_applications_table.name": "Nomo", + "scenes.app.integrations_parameters.company_applications_table.title": "Instalita en via kompanio", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Kreodato", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Versio", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Sukcese forigita {{$1}} de via kompanio", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Sukcese aldonis {{$1}} en via kompanio", + "scenes.apps.messages.input.replied_to": "respondis al ", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Defaŭlta laborspaco", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Aŭtomate invitu ĉiujn novajn firmaajn uzantojn al ĉi tiu laborspaco", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Vi estas forigonta {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Vi ankoraŭ havas {{$1}} membrojn en {{$2}}. Vi devus forigi ĉiujn membrojn por povi forigi ĉi tiun laborspacon.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Mi komprenas, ke ĉiuj mesaĝoj kaj dosieroj de mia laborspaco estos forigitaj.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Maksimuma logograndeco estas 5mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Malbona formato, nur png gif kaj jpg estas permesitaj", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Nekonata eraro", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Eraro", + "scenes.join.create_the_company_button": "Kreu la kompanion", + "scenes.join.join_workspace_from_company": "Aliĝu al {{$1}} de {{$2}}!", + "scenes.join.twake_description": "Twake estas malfermfonta cifereca laborejo konstruita por plibonigi vian teaman produktivecon", + "scenes.join.login_first_button": "Ensalutu aŭ kreu konton unue", + "scenes.join.join_the_team_button": "Aliĝu al la teamo", + "scenes.app.channelsbar.currentuser.reset": "Restarigi", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Neniu komando trovita", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Skribu almenaŭ tri leterojn por montri uzantojn", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Neniu uzanto trovita", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Neniu emoji trovita", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} skribas...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} kaj {{$2}} skribas...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} kaj {{$3}} pliaj uzantoj skribas...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Via firmao atingis ĝian maksimuman limon de {{$1}} membroj. Bonvolu ", + "components.locked_features_components.locked_invite_alert.message_link": "altgradigu vian kompanion", + "components.locked_features_components.locked_invite_alert.message_part_2": " por inviti pliajn membrojn.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " kontaktu la posedanton aŭ administranton de via kompanio.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Vidu ĉiujn miajn firmaanojn sur la konzolo", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Priskribu vian aplikaĵon per kelkaj vortoj", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Nova integriĝo", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Mi komprenas, ke la posedanto kaj administrantoj de ĉi tiu kompanio povos modifi kaj publikigi ĉi tiun aplikaĵon.", + "twake.application.access.title": "Elektu la ĝustajn mediojn por via aplikaĵo.", + "twake.application.access.no_default_scopes_available'": "Ĉi tiu integriĝo ne havas aliron {{$1}}.", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "la Twake API-dokumentado", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Se vi ne scias kiel plenigi ĉi tiujn, iru al ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Privata ŝlosilo", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Sukcese forigita aplikaĵo {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Eraro dum forigo de aplikaĵo {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Sukcese {{$1}} aplikaĵo!", + "scenes.app.integrations_parameters.add_application": "Nova integriĝo", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Agordoj por programistoj", + "components.rich_text_editor.plugins.suggestions.loading": "Serĉante pli", + "components.open_desktop_popup.subtitle": "malfermita en Twake-aplikaĵo", + "components.open_desktop_popup.open_here_link": "Malfermu ĉi tie anstataŭe", + "molecules.download_banner.title": "Profitu la plej grandan parton de Twake, elŝutu la labortablon nun", + "molecules.download_banner.download_button": "Elŝutu labortablan apon", + "scenes.app.channelsbar.channel_copy_link": "Kopiu kanala ligilo", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Sukcese ĝisdatigita", + "components.searchpopup.no_results_for": "Ne estis rezultoj por", + "components.searchpopup.try_new_search": "Provu novan serĉon", + "components.searchpopup.all": "Ĉiuj", + "components.searchpopup.chats": "Babiloj", + "components.searchpopup.media": "Amaskomunikiloj", + "components.searchpopup.files": "Dosieroj", + "components.searchpopup.recent_chats": "Lastatempaj babilejoj", + "components.searchpopup.recent_media": "Lastatempaj amaskomunikiloj", + "components.searchpopup.recent_files": "Lastatempaj dosieroj", + "components.searchpopup.recent_channels_and_contacts": "Lastatempaj kanaloj kaj kontaktoj", + "components.searchpopup.header_title": "Serĉi", + "components.searchpopup.scope.company": "en tuta kompanio", + "components.searchpopup.scope.channel": "en ĉi tiu kanalo", + "components.searchpopup.channels": "Kanaloj", + "components.searchpopup.messages": "Mesaĝoj" +} diff --git a/twake/frontend/public/locales/es.json b/twake/frontend/public/locales/es.json index b3ba8801f4..9e2b5d0cdc 100644 --- a/twake/frontend/public/locales/es.json +++ b/twake/frontend/public/locales/es.json @@ -827,5 +827,84 @@ "components.emoji_picker.categories.activity": "Actividad", "scenes.client.main_view.main_header.search_input": "Buscar", "general.pause": "Pausa", - "scenes.apps.messages.input.replied_to": "respondió a " + "scenes.apps.messages.input.replied_to": "respondió a ", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Escriba al menos tres letras para mostrar los usuarios", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "No se han encontrado usuarios", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "No se han encontrado emojis", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "No se han encontrado comandos", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Copiado correctamente al portapapeles", + "scenes.app.popup.adduser.magiclinks.action_copy": "Dupdo", + "scenes.app.popup.adduser.magiclinks.action_generate": "Generar", + "scenes.join.login_first_button": "Inicie sesión o cree una cuenta primero", + "scenes.join.join_the_team_button": "Únete al equipo", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Enlace de invitación al espacio de trabajo", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Nuevo enlace generado", + "scenes.join.loading": "Cargando…", + "scenes.join.wrong_link_title": "Este enlace ya no está disponible.", + "scenes.join.wrong_link_description": "Pídale a la persona que lo invitó a unirse a esta empresa un nuevo enlace o cree su propia empresa", + "scenes.join.create_the_company_button": "Crea la empresa", + "scenes.join.join_workspace_from_company": "¡Únase a {{$1}} desde {{$2}}!", + "scenes.join.twake_description": "Twake es un espacio de trabajo digital de código abierto creado para mejorar la productividad de su equipo", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Número de mensajes", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "En la versión gratuita de Twake, no puede acceder a más mensajes que {{$1}} más recientes.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Mostrar más planes", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} está escribiendo...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} y {{$2}} están escribiendo...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} y {{$3}} usuarios más están escribiendo...", + "scenes.apps.messages.message.types.no_message_in_thread": "Nadie respondió todavía.", + "login.login_error": "Error durante el inicio de sesión", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Espacio de trabajo predeterminado", + "login.create_account": "Crear una cuenta", + "'": "'", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Nadie te ha invitado a un espacio de trabajo todavía.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Invite automáticamente a todos los usuarios del espacio de trabajo a este canal", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Estás a punto de eliminar {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Aún tienes {{$1}} miembros en {{$2}}. Debe eliminar todos los miembros para poder eliminar este espacio de trabajo.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Entiendo que se eliminarán todos los mensajes y archivos de mi espacio de trabajo.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "El tamaño máximo del logotipo es de 5 MB", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Formato incorrecto, solo se permiten png gif y jpg", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Error desconocido", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Error", + "scenes.app.channelsbar.currentuser.reset": "Reiniciar", + "components.locked_features_components.locked_invite_alert.message_part_1": "Su empresa ha alcanzado el número máximo de {{$1}} miembros. Por favor, ", + "components.locked_features_components.locked_invite_alert.message_link": "actualice su empresa", + "components.locked_features_components.locked_invite_alert.message_part_2": " para invitar a más miembros.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " entre en contacto con el propietario o administrador de su empresa.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Ver todos los miembros de mi empresa en la consola", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "¡Describa su aplicación en pocas palabras", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Nueva integración", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Entiendo que el propietario y los administradores de esta empresa podrán modificar y publicar esta aplicación.", + "twake.application.access.title": "Seleccione los alcances adecuados para su aplicación.", + "twake.application.access.no_default_scopes_available'": "Esta integración no tiene ningún acceso {{$1}}", + "\"": "\"", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "la documentación de la API de Twake", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Si no sabe cómo llenarlos, vaya a ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Llave privada", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "¡Aplicación eliminada con éxito {{$1}}!", + "scenes.app.integrations_parameters.add_application": "Nueva integración", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Configuración de desarrollador", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "¡Error al eliminar la aplicación {{$1}}!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "¡Aplicación exitosa {{$1}}!", + "components.rich_text_editor.plugins.suggestions.loading": "Buscando por mas", + "components.open_desktop_popup.subtitle": "abierto en la aplicación Twake", + "components.open_desktop_popup.open_here_link": "Abrir aquí en su lugar", + "molecules.download_banner.title": "Aproveche al máximo Twake, descargue la aplicación de escritorio ahora", + "molecules.download_banner.download_button": "Descargar aplicación de escritorio", + "scenes.app.channelsbar.channel_copy_link": "Copiar enlace del canal", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Actualizado exitosamente", + "components.searchpopup.media": "Medios de comunicación", + "components.searchpopup.files": "archivos", + "components.searchpopup.recent_chats": "Chats recientes", + "components.searchpopup.recent_media": "Medios recientes", + "components.searchpopup.recent_files": "Archivos recientes", + "components.searchpopup.recent_channels_and_contacts": "Canales y contactos recientes", + "components.searchpopup.no_results_for": "No hubo resultados para", + "components.searchpopup.try_new_search": "Prueba una nueva búsqueda", + "components.searchpopup.all": "Todos", + "components.searchpopup.chats": "charlas", + "components.searchpopup.header_title": "Búsqueda", + "components.searchpopup.scope.company": "en toda compañía", + "components.searchpopup.scope.channel": "en este canal", + "components.searchpopup.channels": "Canales", + "components.searchpopup.messages": "Mensajes" } diff --git a/twake/frontend/public/locales/eu.json b/twake/frontend/public/locales/eu.json index 2f3b67c86f..ac42333b5c 100644 --- a/twake/frontend/public/locales/eu.json +++ b/twake/frontend/public/locales/eu.json @@ -3,5 +3,908 @@ "general.create": "Sortu", "general.cancel": "Ezeztatu", "general.save": "Gorde", - "general.close": "Itxi" -} \ No newline at end of file + "general.close": "Itxi", + "scenes.app.popup.appsparameters.pages.error_check_needed": "Akats bat gertatu da; egiaztatu zure informazioa.", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Joan dokumentaziora zure konfigurazioa JSON formatuan sortzeko.", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Hurrengo Ekitaldian bidaliko diren datu pasiboak", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Ezarri mugikorreko jakinarazpenen maiztasuna.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Jakinarazpenen maiztasuna", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Nabarmendu gako-hitz hauek:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Ezarri posta elektronikoko jakinarazpenen maiztasuna.", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Aukeratu jakinarazpenak jasotzen ez dituzun epe bat.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Ez molestatu gauez", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Integrazioak", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Aldatu enpresa honen izena", + "scenes.apps.calendar.export_view_menu": "Esportatu ikuspegia...", + "scenes.apps.calendar.ics_subscription_menu": "Lortu ICS harpidetza esteka", + "scenes.apps.calendar.modals.event_title_placeholder": "Izenburua", + "scenes.apps.calendar.modals.modify_event_button": "Editatu gertaera", + "scenes.apps.calendar.modals.part.participants": "Parte hartzaileak", + "scenes.apps.calendar.modals.participants_event": "Parte hartzaileak", + "scenes.apps.calendar.modals.reminders": "Oroigarriak", + "scenes.apps.calendar.modals.remove_button": "Ezabatu", + "scenes.apps.calendar.modals.remove_event_button": "Ezabatu gertaera", + "scenes.apps.calendar.modify_calendar_menu": "Editatu egutegia", + "scenes.apps.calendar.month_option": "Hilabetea", + "scenes.apps.calendar.my_calendar": "Nire egutegia", + "scenes.apps.calendar.my_calendar_menu": "Nire egutegia", + "scenes.apps.drive.add_button": "Gehitu", + "scenes.apps.drive.message_added_file": "{{$1}} {{$2}} bidali du.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} hainbat fitxategi bidali ditu.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} fitxategi bat bidali du.", + "scenes.apps.drive.choose_folder_button": "Aukeratu direktorio bat", + "scenes.apps.drive.go_trash_menu": "Joan zaborrontzira", + "scenes.apps.drive.import_from_computer_menu": "Ordenagailutik kargatu", + "scenes.apps.drive.new_file_menu": "Fitxategi berria", + "scenes.apps.drive.new_file_title": "Fitxategi berria", + "scenes.apps.drive.new_external_storage": "Kanpoko biltegiratze berria", + "scenes.apps.drive.new_folder_title": "Karpeta berria", + "scenes.apps.drive.no_file_alert": "Ez duzu fitxategi bat sortzeko aukera ematen duen aplikaziorik.", + "scenes.apps.drive.no_storage_app_alert": "Ez duzu kanpoko biltegia gehitzeko aukera ematen duen aplikaziorik.", + "scenes.apps.drive.remove_definitely_menu": "Ezabatu betiko", + "scenes.apps.drive.restore_menu": "Berreskuratu", + "scenes.apps.drive.throw_menu": "Bidali zakarrontzira", + "scenes.apps.drive.trash_empty_menu": "Zaborrontzia hustu", + "scenes.apps.drive.unconfigured_tab": "Fitxa hau ez dago konfiguratuta oraindik.", + "scenes.apps.drive.viewer.loading_preview_message": "Kargatzen...", + "scenes.apps.drive.viewer.no_preview_message": "Ezin da fitxategi mota hau ikusi.", + "scenes.apps.messages.input.emoji": "Emojia", + "scenes.apps.messages.input.hide_formatting": "Ezkutatu formatua", + "scenes.apps.tasks.board.tasks.add_subtask": "Gehitu azpizeregin bat", + "scenes.apps.tasks.board.tasks.use_deadline": "Erabili epea", + "scenes.apps.tasks.board.tasks.use_starttime": "Erabili hasiera-ordua", + "scenes.apps.tasks.board.tasks.in_list": "Zerrendan", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "Utzi gonbidapena", + "scenes.apps.account.account.fullname": "Izen osoa", + "login.email_login": "Posta elektronikoa / Saioa hasi", + "scenes.apps.account.account.password_for_user": "Zure erabiltzailearen pasahitza", + "scenes.apps.account.account.send_info": "Bidali kredentzial-informazio hau zure erabiltzaileari.", + "components.listmanager.filter": "Iragazkia", + "components.upload.drop_files": "Jaregin zure fitxategiak hemen", + "components.workspace.list_manager.no_workspace": "Lan-esparrurik ez", + "components.searchpopup.loading": "Emaitza gehiago kargatzen", + "components.searchpopup.filter_ws": "Iragazi lan-eremuak", + "components.searchpopup.tags": "Etiketak", + "components.searchpopup.sender": "Bidaltzailea", + "components.searchpopup.mentions": "Aipamenak", + "scenes.apps.drive.used": "karpeta honetan erabiltzen da", + "components.reminder.notification": "Jakinarazpena", + "components.reminder.hours_bef": "orduak lehenago", + "scenes.app.mainview.discussion": "Eztabaida", + "components.attachmentpicker.from_twake": "Twake Documents-etik", + "components.attachmentpicker.remove_attach": "Kendu eranskina", + "scenes.apps.drive.remove_attachs": "Kendu eranskinak", + "components.drive.elements.see": "Ikusi", + "scenes.client.channelbar.channelmemberslist.title": "Erabiltzaileak {{$1}}", + "scenes.client.channelbar.channelmemberslist.loader": "Gehiago kargatu", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Gehitu edo bilatu erabiltzailea", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Kendu kanaletik", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Sartu kanal batean", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "Aplikazio", + "scenes.client.channelbar.channelmemberslist.no_members": "Kanal honetan ez dago erabiltzailerik, Gehitu erabiltzaileak sakatuta gonbida ditzakezu.", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Ezkutatu eztabaida", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} mezu elektronikoak gehituko dira", + "components.newversion.new_version_component.row.part_1": "Twake bertsio zaharkitua exekutatzen ari zara", + "components.newversion.new_version_component.row.part_2": "aplikazioa berriro kargatzea eta gure funtzio berriez gozatzea gomendatzen dizugu!", + "components.newversion.new_version_component.link": "Egin klik hemen berriro kargatzeko", + "components.newversion.new_version_modal.title": "Eguneratze berria eskuragarri!", + "components.inputs.input_with_select.input.placeholder": "Kanalaren izena", + "components.inputs.input_with_select.select.placeholder": "Atalaren izena", + "components.inputs.input_with_select.select.no_sections": "Hasi zure lehen kanalaren atalaren izena idazten.", + "components.inputs.input_with_select.button.tooltip": "Ezarri kanal atal bat", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}}-k {{$2}} gehitu du kanalean", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} konektore bat kendu du {{$2}}", + "components.alert.leave_private_channel.title": "Ziur kanala utzi nahi duzula?", + "components.alert.leave_private_channel.description": "Ezingo zara berriro sartu kanal pribatu honetan norbaitek gonbidatzen zaituen artean.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Ez zara kide", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Gehiago kargatu", + "components.unverified_account.verification_details": "Honi egiaztatzeko xehetasunak bidali dizkiogu", + "components.account_verification_status_sentence": "Zure kontuaren egoera hau da: {{$1}}", + "components.account_verication_status_unverified": "Egiaztatu gabe", + "components.account_verication_status_blocked": "Blokeatua", + "components.unverified_account.re_send_email": "Ez al duzu mezu elektronikoa jaso?", + "components.blocked_account.trial_period_over": "Zure proba-aldia amaitu da. Zure kontua desblokeatzeko eta funtzio guztietarako sarbidea lortzeko, egiaztatu zure kontua posta elektronikoaren berrespenaren bidez", + "components.add_mails_workspace.button": "Hasi Twake erabiltzen", + "components.add_mails_workspace.title_1": "Gehitu erabiltzaile batzuk", + "components.add_mails_workspace.title_2": "Twake talde lankidetzarako tresna bat da, beraz, gonbidatu erabiltzaile batzuk zuretzat sortu dugun lan-eremu bat probatzera.", + "components.add_mails_workspace.text_area_placeholder": "Sartu zure erabiltzaileen helbide elektronikoak*", + "components.verify_mail.title_1": "Zorionak", + "components.verify_mail.title_2": "Twake-ren erabiltzaile ofiziala zara orain!", + "components.verify_mail.button": "Gehitu erabiltzailea", + "services.console_services.toaster.success_verify_email": "Egiaztapen-esteka bat bidali da zure posta-kontura", + "scenes.app.popup.workspaceparameter.pages.table_title": "Izena", + "scenes.client.main_view.main_header.search_input": "Bilatu", + "scenes.apps.drive.new_link_title": "Esteka berria", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Enpresatik kendu", + "scenes.app.integrations_parameters.company_applications_table.name": "Izena", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Behar bezala gehitu da {{$1}} zure enpresan", + "scenes.apps.messages.input.replied_to": "erantzun zion ", + "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50 - 99 erabiltzaile", + "components.locked_features.locked_only_office_popup.title": "Ezin duzu fitxategi hau editatu", + "components.drive.new_versions": "Gehitu bertsio berri bat", + "scenes.apps.parameters.group_sections.workspaces": "Lan-eremuak", + "scenes.apps.calendar.my_calendar_label": "Nire egutegia", + "general.help.documentation": "Dokumentazioa", + "general.send": "Mezua bidali", + "general.help.support": "Laguntza", + "scenes.apps.parameters.workspace_sections.members.pending": "Zain dauden mezu elektronikoak", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} ezarpenak", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Sortu kanal bat", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} kendu du {{$2}} fitxa {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} eta {{$3}}", + "scenes.login.create_account.firstname": "Izena", + "scenes.apps.tasks.board.ends": "Egin beharrekoa", + "general.user.role.company.member": "Kide", + "scenes.apps.messages.input.send_message": "Mezua bidali", + "components.locked_features.locked_workspace_popup.subtitle": "Doako bertsioan, lan-eremu bakarra izan dezakezu zure enpresan.", + "general.unarchive": "Desartxiboa", + "components.users_picker.add_me": "Gehitu nazazu", + "general.retry": "Saiatu berriro", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Bilatu aplikazioak...", + "scenes.app.popup.workspaceparameter.pages.show_button": "Bistaratzea", + "components.workspace.list_manager.current_company": "Egungo enpresa", + "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000 - 4999 erabiltzaile", + "scenes.login.create_account.fill_in_email": "Zure posta elektronikoa mezu elektroniko zuzen batekin bete behar duzu", + "scenes.apps.calendar.modals.remove_event_text": "Gertaera ezabatu?", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Garraioa / Logistika", + "scenes.apps.account.account.password_modal.old_password": "Oraingo pasahitza", + "scenes.apps.messages.messageslist.go_last_message_button": "Joan azken mezura", + "general.add": "Gehitu", + "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500 - 999 erabiltzaile", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "Kimika", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "Ehungintza / Arropa / Oinetakoak", + "general.archive": "Artxiboa", + "scenes.login.forgot_password.mail_doesnt_exist": "E-mail hau ez da existitzen", + "scenes.app.popup.userparameter.personnal_workspaces_title": "Zure lan-eremuak", + "scenes.app.popup.workspaceparameter.pages.name_label": "Lan-eremuaren izena", + "scenes.apps.drive.open_link": "Ireki esteka leiho berri batean", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Argitalpena / Komunikazioa / Multimedia", + "components.application.messages": "Mezuak", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "Hezkuntza", + "scenes.apps.board.kanban": "Kanban", + "scenes.login.forgot_password.password": "Pasahitza", + "components.unverified_account.typography_text_danger": "{{$1}} egun geratzen zaizu proba-aldian. Probako kontua 7 egun igaro ondoren blokeatuko da eta behin betiko ezabatuko da erregistratu eta hilabete igaro ondoren. Zure kontua egiazta dezakezu bidali dizugun egiaztapen-mezuan dagoen \"Egiaztatu nire kontua\" botoian klik eginez.", + "scenes.app.popup.workspaceparameter.pages.title": "Laneko eremuaren ezarpenak", + "scenes.app.popup.workspaceparameter.pages.install_button": "Instalatu", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Laneko eremuaren ezarpenak", + "scenes.app.channelsbar.currentuser.disable_notifications": "Desgaitu", + "general.delete": "Ezabatu", + "general.continue": "Jarraitu", + "components.user_picker.modal_no_result": "Ez da emaitzarik aurkitu", + "scenes.app.workspaces.create_company.group_data.group_type.public_organization": "Erakunde publikoa", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Elkartea, kluba edo ongintza", + "scenes.app.workspaces.create_company.group_data.group_type.other_group": "Bestela", + "scenes.app.workspaces.create_company.group_data.group_size": "Taldearen tamaina", + "scenes.app.workspaces.create_company.group_data.group_size.less_3": "4 erabiltzaile baino gutxiago", + "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4-10 erabiltzaile", + "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "5000 erabiltzaile baino gehiago", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "Jarduera nagusia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Janari", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "Bankua / Aseguruak", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "Eraikuntza / Materiales de construcción", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "Higiezinak", + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "Materialak", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Merkataritza / Merkataritza / Banaketa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Ikasketak eta aholkularitza", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "Industria farmazeutikoa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "Informatika / Telekomunikazioa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "Enpresa zerbitzuak", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Entretenimendua", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Ikerketa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Administrazioa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "Bestela", + "scenes.app.workspaces.create_company.invitations.title": "Konfiguratu zure lan-eremua.", + "scenes.app.header.disconnected": "Deskonektatuta zaude", + "scenes.app.header.disconnected.reload": "Berriz kargatu", + "scenes.app.header.alt_notifications": "Jakinarazpenak", + "scenes.apps.calendar.calendar.list_btn": "Zerrenda", + "scenes.apps.calendar.event_edition.deadline_tag": "Epemuga", + "scenes.apps.calendar.event_edition.checkbox_all_day": "Egun osoan", + "scenes.apps.calendar.event_edition.title_confidentiality": "Konfidentzialtasuna", + "scenes.apps.calendar.event_view.article_until": "to", + "scenes.apps.calendar.calendar_modal.participants": "Parte hartzaileak", + "scenes.apps.calendar.calendar_modal.placeholder": "Izena", + "scenes.apps.calendar.left.calendars": "Egutegiak", + "scenes.apps.drive.left.search": "Bilatu", + "scenes.apps.drive.navigators.navigator_content.directory_name": "Direktorioaren izena", + "scenes.apps.drive.navigators.navigator_labels.title": "Etiketak", + "scenes.apps.drive.navigators.new_file.untitled": "Izenbururik gabe", + "scenes.apps.drive.navigators.new_file.create_file.type": "Mota", + "scenes.apps.drive.navigators.new_file": "Fitxategi berria", + "scenes.apps.drive.preview_bloc.operations_download": "Deskargatu", + "scenes.apps.drive.preview_bloc.error_file": "Fitxategia ez da aurkitu", + "scenes.apps.drive.right_preview.operations_restore": "Berreskuratu", + "scenes.apps.drive.right_preview.operations_delete": "Eraman zaborrontzira", + "scenes.apps.drive.right_preview.public_link": "Esteka publikoa", + "scenes.apps.messages.messages": "Mezuak", + "scenes.apps.messages.chatbox.chat.delete_message": "Ezabatu mezu hau", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "Ezabatu mezua", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Izena", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Gehitu gogokoetara", + "scenes.apps.messages.left_bar.stream.notifications": "Jakinarazpenak...", + "scenes.apps.messages.left_bar.stream.notifications.all": "Edozein mezu", + "scenes.apps.messages.left_bar.stream.notifications.never": "Ezer ez", + "scenes.apps.parameters.workspace_sections.workspace": "Langunea", + "scenes.apps.parameters.workspace_sections.members": "Parte hartzaileak", + "scenes.apps.parameters.group_sections.apps": "Aplikazioak", + "scenes.apps.account.title": "Kontuaren parametroak", + "scenes.apps.account.account.menu_title": "Kontua", + "scenes.apps.account.languages.menu_title": "Hizkuntza", + "scenes.apps.account.account.firstname": "Izena", + "scenes.apps.account.account.lastname": "Abizena", + "scenes.apps.account.account.username": "Erabiltzaile izena", + "scenes.apps.account.account.change_username": "Aldatu zure erabiltzaile-izen berezia.", + "scenes.apps.account.account.email_add": "Gehitu e-mail berria", + "scenes.apps.account.account.email_add_modal.invalid_code": "Kode hau baliogabea da", + "scenes.apps.account.account.password": "Pasahitza", + "scenes.apps.account.account.password_modal.password": "Pasahitz berria", + "scenes.apps.account.account.password_modal.bad_old_password": "Pasahitz zaharra ez da zuzena.", + "scenes.apps.account.account.password_modal.bad_password": "Zure pasahitzak ez datoz bat edo laburregiak dira. Mesedez, idatzi gutxienez 8 karaktere dituen pasahitza.", + "scenes.apps.account.account.logout": "Saioa amaitu", + "scenes.apps.account.languages.text": "Aldatu Twake hizkuntza.", + "scenes.apps.account.notifications.title": "Jakinarazpenak", + "scenes.apps.account.notifications.keywords_subtitle": "Gako-hitzak", + "scenes.apps.account.notifications.keywords_placeholder": "garatzailea, wifia, kodea, ...", + "scenes.apps.account.notifications.disturb_option_a": "Ez bidali push jakinarazpen artean ", + "scenes.apps.account.notifications.disturb_option_b": " eta ", + "scenes.apps.account.notifications.disturb_option_c": " (tokiko ordu-eremua)", + "scenes.apps.account.notifications.devices_subtitle": "Gailuaren jakinarazpenak", + "scenes.apps.account.notifications.devices_option_ever": "Bidali beti push jakinarazpenak", + "scenes.apps.account.notifications.devices_option_inactive": "Bidali push jakinarazpenak mahaigainean inaktibo nagoenean", + "scenes.apps.account.notifications.devices_option_never": "Inoiz ez bidali push jakinarazpenik", + "scenes.apps.account.notifications.privacy_subtitle": "Pribatutasuna", + "scenes.apps.account.notifications.mail_subtitle": "Posta elektroniko bidezko jakinarazpenak", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Luzapena", + "scenes.apps.parameters.workspace_sections.members.members": "Erabiltzaileak", + "scenes.apps.parameters.workspace_sections.members.invite": "Gonbidatu erabiltzaile berria", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "Gehitu erabiltzailea", + "scenes.apps.tasks.boards": "Oholak", + "scenes.apps.tasks.connectors_search_menu": "Bilatu konektoreak...", + "scenes.apps.tasks.no_connectors_menu_text": "Ez duzu egutegi batera konektatu daitekeen konektorerik.", + "scenes.apps.tasks.unconfigured_tab": "Fitxa hau ez dago konfiguratuta oraindik.", + "scenes.apps.tasks.choose_board_button": "Aukeratu taula bat", + "scenes.apps.tasks.new_board.title": "Taula berria", + "scenes.apps.tasks.new_board.edit_title": "Editatu taula", + "scenes.apps.tasks.task": "Zeregin", + "scenes.apps.tasks.no_tasks": "Zereginik ez", + "scenes.apps.tasks.task_status.todo": "Egin", + "scenes.apps.tasks.task_status.current": "Oraingoa", + "scenes.apps.tasks.task_status.done": "Eginda", + "scenes.apps.tasks.task.description": "Deskribapena", + "scenes.apps.tasks.task.assignees": "Esleipendunak", + "scenes.apps.tasks.task.edit.dates": "Datak", + "scenes.apps.tasks.list_modal.modify_list": "Aldatu zerrenda", + "scenes.apps.tasks.list_modal.new_list": "Zerrenda berria", + "scenes.apps.tasks.list_modal.remove": "Kendu zerrenda eta zereginak", + "scenes.apps.tasks.list_modal.predefined_participants": "Aurrez zehaztutako parte-hartzaileak", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Kendu artxibatutako zereginak ({{$1}})", + "scenes.login.footer.go_to_twake": "Joan twakeapp.com helbidera", + "scenes.login.footer.branding": "{{$1}} ({{$2}}) Twake zerbitzari pribatu batean zaude. ", + "scenes.login.create_account.title": "Sortu kontu berri bat", + "scenes.login.create_account.email": "Posta elektronikoa", + "scenes.login.create_account.email_used": "Posta elektroniko hau dagoeneko erabiltzen ari da.", + "scenes.login.create_account.username_already_exist": "Erabiltzaile-izen hau dagoeneko erabiltzen ari da", + "scenes.login.create_account.fill_in_username": "Zure erabiltzaile-izena bete behar duzu", + "scenes.login.create_account.too_short_password": "Zure pasahitzak 8 karaktere izan behar ditu gutxienez.", + "scenes.login.create_account.newsletter": "Jaso Twake-ri buruzko informazioa", + "scenes.login.create_account.lastname": "Abizena", + "scenes.login.forgot_password.title": "Pasahitza ahaztua?", + "scenes.login.forgot_password.text": "9 digituko kode bat jasoko duzu posta elektronikoz zure nortasuna egiaztatzeko.", + "scenes.login.forgot_password.email_to_recover": "Posta elektronikoa berreskuratzeko", + "scenes.login.forgot_password.invalid_code": "Kode honek ez du balio.", + "scenes.login.forgot_password.text3": "Sartu pasahitz berri bat zure konturako.", + "scenes.login.forgot_password.password2": "Pasahitza baieztatu", + "scenes.login.forgot_password.password_dont_match": "Zure pasahitzak ez datoz bat edo laburregiak dira. Mesedez, idatzi gutxienez 8 karaktere dituen pasahitza.", + "scenes.login.home.subtitle": "Pozik zu ikusteaz", + "scenes.login.home.unable_to_connect": "Kredentzialak baliogabeak", + "scenes.login.home.password": "Pasahitza", + "scenes.login.home.login_btn": "Saioa hasi", + "scenes.login.home.lost_password": "Pasahitza ahaztua?", + "scenes.login.home.create_account": "Kontu bat sortu", + "scenes.login.create_account.password": "Pasahitza", + "scenes.login.create_account.step_1_subtitle": "Ezin da sinpleagoa izan; informazio pixka bat besterik ez dugu behar.", + "scenes.login.create_account.step_2_subtitle_a": "Gehitu zure izen osoa beste erabiltzaileek zu ezagutu dezaten.", + "scenes.login.create_account.step_2_subtitle_b": "Zure telefono-zenbakiak pribatua izaten jarraitzen du.", + "scenes.login.create_account.step_3_mail_sent": "Posta elektronikoz aktibatzeko esteka bidali dizugu.", + "scenes.login.create_account.step_3_subtitle": "Azken urratsa: robot bat ez zarela egiaztatu behar dugu!", + "scenes.app.workspaces.create_company.company_name.placeholder": "Enpresaren izena", + "scenes.app.workspaces.create_company.company_name.title_1": "Hasi,", + "scenes.app.workspaces.create_company.company_name.title_2": "adierazi zure enpresaren izena.", + "scenes.app.workspaces.create_company.default_workspace_name": "Nagusia", + "scenes.app.workspaces.create_company.importations.title_1": "Dagoeneko tresna digitalekin lan egiten duzu? Inportatu edo integratu zure tresnak orain!", + "scenes.app.workspaces.create_company.importations.title_2": "Ez kezkatu, geroago egin dezakezu!", + "scenes.app.workspaces.create_company.invitations.title_2": "Gehitu erabiltzaileak zure taldean.", + "scenes.app.workspaces.create_company.title": "Sortu nire enpresa", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "Gehitu bigarren mailako mezu elektroniko bat", + "scenes.app.workspaces.welcome_page.added_to_company": "Gonbidatu zaituzte ", + "scenes.app.workspaces.welcome_page.create_my_company": "Sortu nire enpresa", + "scenes.app.workspaces.welcome_page.lets_go": "Goazen!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Beste helbide elektroniko bat erabilita gonbidatu zaituzte?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "A, tira... Badirudi oraindik inork ez zaituela gonbidatu lan gune batera.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Lan egiteko prest zaude orain.", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Hainbat helbide elektroniko lotu ditzakezu zure kontuarekin; helbide bakarra erabiliko da jakinarazpenak bidaltzeko.", + "scenes.app.workspaces.welcome_page.main_mail_title": "Helbide nagusia", + "scenes.app.workspaces.welcome_page.other_mail_title": "Bigarren mailako helbideak", + "scenes.app.workspaces.welcome_page.add_new_email": "Gehitu e-mail bat", + "scenes.app.workspaces.welcome_page.code_verification": "Egiaztapen-kodea", + "scenes.app.workspaces.welcome_page.new_email": "Gehitu bigarren mailako mezu elektroniko bat", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Egiaztapen-kode bat bidali dizugu {{$1}} bidez", + "scenes.app.workspaces.welcome_page.done": "bukatu dut", + "scenes.login.forgot_password.finished": "Zure pasahitza behar bezala eguneratu da.", + "scenes.apps.account.account.description_main": "Zure helbide nagusia da Twake-k zure jakinarazpenak bidaltzen dituena. Zure bigarren mailako helbideak haiek erabiltzen dituzten lan-eremuetara automatikoki gonbidatzeko aukera ematen dute.", + "scenes.apps.account.account.emails.description": "Kudeatu zure helbide elektroniko desberdinak.", + "scenes.apps.account.account.make_main": "Ezarri nagusia", + "scenes.apps.account.account.password.description": "Aldatu pasahitza.", + "scenes.apps.account.identity": "Identitatea", + "scenes.apps.account.identity.description": "Aldatu zure izena, abizena eta profilaren irudia Twake-ko beste erabiltzaileek ikusgai.", + "scenes.apps.account.preference": "Hobespenak", + "general.open": "Ireki", + "scenes.apps.account.thumbnail.max_weight": "Gehienezko tamaina 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "Berretsi e-mail hau", + "app.name.twake_calendar": "Egutegia", + "app.name.twake_drive": "Dokumentuak", + "app.name.twake_tasks": "Zereginak", + "components.calendar.repetition.everyday": "Egunero", + "components.calendar.repetition.does_not_repeat": "Ez da errepikatzen", + "components.calendar.repetition.weekly_on": "Astero {{$1}}", + "components.calendar.repetition.monthly_on": "Hilero {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Hilero egunean {{$1}}", + "components.calendar.repetition.annually_on": "Urtero {{$1}}", + "components.calendar.repetition.every_weekday": "Astegunero (astelehenetik ostiralera)", + "components.calendar.repetition.custom": "Pertsonalizatua...", + "components.calendar.repetition.repeat": "Errepikatu bakoitzean", + "components.calendar.repetition.ends": "Amaierak", + "components.calendar.repetition.never": "Inoiz ez", + "components.calendar.repetition.repeat_on": "Errepikatu", + "scenes.app.channelsbar.currentuser.add_apps": "Bilatu aplikazioak", + "scenes.app.channelsbar.currentuser.change_my_status": "Aldatu nire egoera", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Sortu lan-eremu bat", + "scenes.app.channelsbar.currentuser.invited_status": "Gonbidatua zara.", + "scenes.app.channelsbar.currentuser.title": "Kontu ezarpenak", + "scenes.app.channelsbar.currentuser.logout": "Amaitu saioa", + "scenes.app.channelsbar.currentuser.update": "Eguneratu", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Desgaitu 9:00ak arte. bihar", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Berriz aktibatu", + "scenes.app.channelsbar.currentuser.user_parameter": "Jakinarazpen-ezarpenak", + "scenes.app.channelsbar.initial_instructions_tutorial": "Aukeratu izen bat, izena eta profileko argazki bat.", + "scenes.app.channelsbar.installation_desktop_tutorial": "Instalatu mahaigaineko aplikazioa", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Gonbidatu erabiltzaileak zure laneko gunera.", + "scenes.app.channelsbar.public_channel_label": "Publiko", + "scenes.app.channelsbar.private_channel_label": "Pribatua", + "scenes.app.channelsbar.sending_message_instruction": "Bidali zure lehen mezua eztabaida batean", + "scenes.app.channelsbar.tutorial_alert": "Ez duzu inoiz marko hau berriro erakutsi?", + "scenes.app.channelsbar.welcome": "Ongi etorri Twake-ra", + "scenes.app.channelsbar.welcoming_message_subtitle": "Egin zaitez Twake-ko profesional bat klik gutxitan!", + "scenes.app.mainview.instruction_current_tab": "Hasi zure ezkerreko kanal bat hautatuz.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Ez duzu kanal batera konektatzeko moduko konektorerik.", + "scenes.app.mainview.tabs.rename": "Aldatu izena", + "scenes.app.mainview.tabs.searching_connectors": "Bilatu konektoreak...", + "scenes.app.popup.adduser.adresses_message": "Mesedez, bereizi helbideak koma edo zuriune batekin. Gogoratu Twake-k zure harpidetzaren arabera gonbidapen kopurua muga dezakeela.", + "scenes.app.popup.appsparameters.pages._app_identity": "Aplikazioaren identitatea", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Probatu zure Twacode mezuen itxura", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Zure aplikazioa argitaratu da, ezin duzu editatu.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Erabili * garapenean IP helbide guztiak baimentzeko.", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "Nire aplikazio harrigarria", + "scenes.app.popup.appsparameters.pages.api_data_description": "Twake APIrako datu erabilgarriak.", + "components.locked_features.locked_only_office_popup.subtitle": "Doako bertsioan, ezin duzu bulegoa bakarrik erabili.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Lanerako gonbidapenaren esteka", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Esteka berria sortu da", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Behar bezala kopiatu da arbelean", + "scenes.app.popup.adduser.magiclinks.action_copy": "Kopiatu", + "scenes.app.popup.adduser.magiclinks.action_generate": "Sortu", + "scenes.app.popup.appsparameters.pages.error_message": "Izen hau beste aplikazio batek erabiltzen du jada; mesedez aukeratu beste bat.", + "scenes.app.popup.appsparameters.pages.filter_information": "Iragazki honek zure API gakoaren erabilera zure konektoreko zerbitzarietara mugatzen du.", + "scenes.app.popup.appsparameters.pages.go_back": "Itzuli", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Izen hau beste aplikazio batek erabiltzen du dagoeneko. Mesedez, aukeratu beste bat.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Izen sinplifikatua", + "scenes.app.popup.appsparameters.pages.installation": "Instalatu.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Hasi zure mezua JSON formatuan idazten.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Barne aplikazioa", + "scenes.app.popup.appsparameters.pages.loading": "Kargatzen...", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Editatu zure aplikazioaren datu publikoak.", + "scenes.app.popup.appsparameters.pages.new_app_title": "Aplikazio berria", + "scenes.app.popup.createworkspacepage.placeholder_name": "Lan-eremuaren izena", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Gonbidatu erabiltzaileak", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Erabiltzaileak", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Enpresak garatutako aplikazioak", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Enpresaren identitatea", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "Enpresaren izena", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "konfigurazioa", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Konfiguratu", + "scenes.app.popup.workspaceparameter.pages.description": "Deskribapena", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Bistaratu hobespenak", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Instalatu aplikazioa lan eremu honetan.", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Zure aplikazioak", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Ordainketak eta harpidetzak", + "scenes.app.workspacesbar.components.change_company_title": "Enpresa aldatu", + "scenes.app.workspacesbar.components.create_company_menu": "Enpresa bat sortu", + "scenes.apps.calendar.add_calendar_menu": "Gehitu egutegi bat", + "scenes.apps.calendar.connectors_menu": "Konektoreak...", + "scenes.apps.calendar.connectors_search_menu": "Bilatu konektoreak...", + "scenes.apps.calendar.create_calendar_title": "Sortu egutegi bat", + "scenes.apps.calendar.day_option": "Eguna", + "scenes.apps.calendar.edit_calendar_title": "Editatu egutegia", + "scenes.apps.calendar.export_title": "Esportatu", + "scenes.apps.calendar.modals.advanced_options": "Aukera aurreratuak", + "scenes.apps.calendar.modals.description_placeholder": "Deskribapena", + "scenes.apps.calendar.modals.details_title": "Xehetasunak", + "scenes.apps.calendar.modals.event_adresse_placeholder": "Helbidea", + "scenes.apps.calendar.modals.event_description_placeholder": "Deskribapena", + "scenes.apps.calendar.no_calendar_text": "Ez duzu egutegirik ezarri lan-eremu honetarako.", + "scenes.apps.calendar.no_connectors_menu_text": "Ez duzu egutegi batera konektatu daitekeen konektorerik.", + "scenes.apps.calendar.remove_calendar_confirmation": "Egutegia eta bere gertaerak betiko ezabatu nahi dituzu?", + "scenes.apps.calendar.today_menu": "Gaur", + "scenes.apps.calendar.week_option": "Astea", + "scenes.apps.calendar.workspace": "Langunea", + "scenes.apps.calendar.workspace_label": "Lan eremu hau", + "scenes.apps.calendar.workspace_menu": "Langunea", + "scenes.apps.drive.choose_file_button": "Hautatu fitxategi bat", + "scenes.apps.drive.create_folder_button": "Sortu", + "scenes.apps.drive.download_button": "Deskargatu", + "scenes.apps.drive.files_subtitle": "Fitxategiak", + "scenes.apps.drive.folder_subtitle": "Karpetak", + "scenes.apps.drive.go_out_trash_menu": "Utzi zaborra", + "scenes.apps.drive.move_text": "Mugitu", + "scenes.apps.drive.viewer.open_with_button": "Ireki...", + "scenes.apps.messages.input.placeholder": "Idatzi mezu bat. Erabili @ erabiltzaile bat aipatzeko.", + "scenes.apps.messages.input.edited": "Editatua", + "scenes.apps.messages.just_you": "Zuretzat bakarrik ikusgai", + "scenes.apps.messages.message.new_messages_bar": "Mezu berriak", + "scenes.apps.messages.message.cancel_button": "Utzi", + "scenes.apps.messages.message.modify_button": "Editatu", + "scenes.apps.messages.input.show_formatting": "Erakutsi formatua", + "scenes.tell_us": "Mesedez, esaiguzu zertan ari zinen:", + "scenes.apps.drive.viewer.download_desktop": "Deskargatu Twake Desktop aplikazioan aurreikusteko", + "scenes.apps.tasks.my_tasks": "Nire zereginak", + "scenes.apps.tasks.board.place_holder": "Kontseiluaren izena", + "scenes.apps.tasks.board.tasks.subtask": "Azpizeregin", + "scenes.apps.tasks.board.starts": "hasten da", + "scenes.apps.tasks.board.list_name": "Zerrendaren izena", + "scenes.app.popup.sync_calendar": "Sinkronizatu zure egutegiak.", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "Enpresaren logotipoa", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "Editatu enpresaren irudia ", + "components.workspace.list_manager.add": "Gehitu lan-eremuak", + "components.workspace.list_manager.current_space": "Egungo lan-espazioa", + "components.workspace.list_manager.all": "Denak", + "components.workspace.calendar.invalid": "Baliogabea", + "components.searchpopup.enter_text": "Sartu testu bat Twake bilatzeko.", + "components.searchpopup.size": "Tamaina", + "components.searchpopup.creation": "Sorkuntza", + "components.searchpopup.update_search": "Eguneratu bilaketa", + "components.searchpopup.last_modif": "Azken aldaketa", + "components.reminder.days_bef": "egun lehenago", + "components.reminder.weeks_bef": "aste lehenago", + "components.reminder.by_email": "Posta elektronikoa", + "scenes.apps.calendar.reminders": "abisua(k)", + "scenes.apps.calendar.video_link": "Egin klik esteka irekitzeko", + "components.tagpicker.notag": "Etiketarik ez", + "scenes.apps.tasks.modals.attachments": "Eranskinak", + "components.calendar.calendarselector.from": "Bertatik", + "scenes.apps.drive.move_text2": "Mugitu", + "components.attachmentpicker.from_computer": "Zure gailutik", + "components.attachmentpicker.file": "Fitxategia", + "components.drive.elements.current_name": "Egungo izena: ", + "scenes.apps.drive.right_preview.public": "Sarbide publikoa", + "components.drive.elements.configurate_mod": "Konfiguratu mod...", + "components.drive.elements.manage_version": "Kudeatu bertsioak", + "scenes.app.popup.createcompany.try_again": "Saiatu berriro mesedez.", + "scenes.app.popup.workspace.edit_temp": "Editatu aldi baterako kontua", + "scenes.apps.tasks.active_tasks": "zeregin aktiboak", + "scenes.apps.drive.right_preview.versions": "Bertsioak", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Kudeatu zure aplikazioak eta konektoreak.", + "scenes.app.popup.appsparameters.pages.icon": "Ikonoa", + "scenes.app.popup.appsparameters.pages.title_informations": "Oinarrizko informazioa", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Aplikazioen kudeaketarekin lotutako informazioa", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Uneko erabiltzailearen IDa", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Uneko lan-eremuaren ID", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Uneko taldearen IDa", + "scenes.app.mainview.channel_description": "Deskribatu kanala", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Gonbidatu automatikoki lan-eremuko erabiltzaile guztiak kanal honetara", + "components.channelworkspacelist.title": "Kanalak", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Bilatu kanala, erabiltzailea edo zuzeneko mezuak", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Sortu fitxa berri bat", + "components.notifications.hidden_notifications_button.children": "Mezu berriak", + "scenes.apps.drive.download_all_button": "Deskargatu guztiak", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}}-k {{$2}} kendu du kanaletik", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} deskribapena aldatu du", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} kanalari izena aldatu dio {{$2}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} konektore berri bat gehitu du {{$2}}", + "components.verify_mail.text": "Lehenik eta behin, zure helbide elektronikoa egiaztatu behar duzu. Hona egiaztapen-esteka bat bidali dugu", + "components.verify_mail.paragraph": "Geroago egin dezakezu nahi baduzu, baina egiaztatu gabeko kontuek Twake-ren bertsio mugatu baterako sarbidea dute", + "services.console_services.toaster.add_emails_error": "Errore bat gertatu da mezu elektronikoak gehitzean", + "services.console_services.toaster.add_email_error_message": "Errore bat gertatu da {{$1}} gehitzean", + "scenes.apps.drive.default_link_name": "Izenbururik gabe", + "components.emoji_picker.input_search_placeholder": "Bilatu", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Ezin duzu {{$2}} fitxategi baino gehiago gehitu mezu batean", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Mezu hau ezabatu duzu", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Bertsioa", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Erakutsi", + "scenes.app.integrations_parameters.company_applications_table.title": "Zure enpresan instalatuta", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Behar bezala ezabatu da {{$1}} zure enpresatik", + "scenes.apps.account.account.emails": "Posta elektronikoak", + "scenes.apps.account.account.main_email": "Posta elektroniko nagusia", + "scenes.apps.account.notifications.sound": "Soinu jakinarazpena", + "scenes.app.popup.appsparameters.pages.application_title": "Aplikazio", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "Zona arriskutsua", + "scenes.app.popup.appsparameters.pages.description_label": "Deskribapena", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Enpresak garatutako aplikazioak", + "scenes.app.popup.appsparameters.pages.string_information": "Kate honek zure aplikazioa identifikatzen du eta mezuen komandoetan erabiliko da.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Lan-eremuaren administratzailea zara.", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Enpresak garatutako aplikazioak", + "scenes.apps.drive.viewer.edit_with_button": "Editatu {{$1}}", + "services.apps.calendar.move_icon": "Mugitu", + "scenes.apps.board.display_as": "Erakutsi gisa", + "scenes.app.popup.workspace.create_temp": "Sortu aldi baterako kontua", + "general.re_send": "Berriz bidali", + "general.verify": "Egiaztatu", + "scenes.app.popup.workspaceparameter.edit_from_console": "Ikusi Kontsolan", + "scenes.apps.calendar.modals.title_placeholder": "Izenburua", + "scenes.apps.account.message_temporary": "Aldi baterako kontu batek Twake-ko kontu arrunt baten moduan funtzionatzen du, baina pasahitza sortzen duzu eta behar izanez gero berrezarri ahal izango duzu.", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Ezin duzu aplikazio hau ezabatu argitaratzen bada.", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Zure aplikazioaren izen sinplifikatua beste aplikazio batek erabiltzen du dagoeneko. Mesedez, aldatu.", + "scenes.app.workspaces.welcome_page.see_you_soon": "Laster arte!", + "scenes.app.workspaces.welcome_page.try_again": "Saiatu berriro", + "scenes.app.workspaces.welcome_page.twake_team": "Esnatu", + "scenes.app.workspaces.welcome_page.welcome_header": "Ongi etorri Twake-ra!", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Ezkutatu mezu pribatuen edukia", + "scenes.no_panic": "Ez zaitez izutu! Besterik gabe, kargatu orri hau Twake konpontzeko.", + "scenes.app.workspaces.components.skip": "Saltatu", + "components.on_boarding.company_billing_banner.link": "enpresaren harpidetza plana", + "components.on_boarding.popups.blocked_company.title": "Zure enpresa blokeatuta dago ordainketa-arazo bat dela eta", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Desgaitu 1 orduz", + "scenes.app.popup.appsparameters.pages.app_update": "Eguneratu aplikazioa {{$1}} (aplikazioa {{$2}} aldiz erabiltzen da).", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Kendu lan-eremutik", + "scenes.app.popup.appsparameters.pages.show_button": "Erakutsi", + "scenes.client.channelbar.channelmemberslist.tag": "Zuk", + "scenes.join.loading": "Kargatzen…", + "scenes.join.wrong_link_title": "Esteka hau jada ez dago erabilgarri", + "scenes.join.wrong_link_description": "Eskatu enpresa honetan sartzera gonbidatu zaituenari esteka berri bat edo sortu zure enpresa", + "scenes.join.create_the_company_button": "Sortu enpresa", + "scenes.join.join_workspace_from_company": "Sartu {{$1}} {{$2}}-tik!", + "scenes.join.twake_description": "Twake zure taldearen produktibitatea hobetzeko kode irekiko lan-espazio digitala da", + "scenes.join.login_first_button": "Hasi saioa edo sortu kontu bat lehenik", + "scenes.join.join_the_team_button": "Sartu taldean", + "scenes.apps.tasks.connectors_menu": "Konektoreak...", + "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11 - 49 erabiltzaile", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Erakutsi mezu pribatuen edukia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Inprimaketa / Papera", + "scenes.app.workspaces.create_company.group_data.group_type.university_school": "Unibertsitatea edo eskola", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Kendu gogokoetatik", + "scenes.app.popup.appsparameters.pages.remove_app": "Ezabatu {{$1}} aplikazioa betiko.", + "scenes.apps.calendar.ics_download_menu": "Deskargatu ICS fitxategi bat", + "general.help": "Laguntza", + "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}} soilik", + "scenes.apps.drive.navigators.navigator_content.files": "Fitxategiak", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Sartu zure aplikazio eta konektoreak", + "scenes.apps.calendar.calendar.week_btn": "Astea", + "general.update": "Eguneratu", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} {{$2}} fitxa berri bat gehitu du {{$3}}", + "components.calendar.repetition.custom_recurrence": "Errepikapen pertsonalizatua", + "general.confirm": "Berretsi", + "general.connexion_status.connected": "Sarean zaude", + "scenes.apps.tasks.list_modal.archive_all_tasks": "Zeregin guztiak artxibatu", + "scenes.login.forgot_password.text2": "9 digituko kodea jasoko duzu. Mesedez, sartu beheko eremuan jarraitzeko.", + "general.back": "Itzuli", + "general.remove": "Kendu", + "general.connexion_status.connecting": "Berriro konektatzen…", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Makineria / Automozioa", + "scenes.apps.drive.trash": "Zaborrontzia", + "components.locked_features.locked_guests_popup.title": "Gonbidatuen funtzioa blokeatuta dago", + "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100 - 499 erabiltzaile", + "components.drive_dropzone.uploading": "Kargatzen...", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Elektronika / Elektrizitatea / Energia", + "scenes.login.create_account.username": "Erabiltzaile izena", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "Aldatu izena {{$1}}", + "components.connectorslistmanager.add_connectors": "Gehitu konektoreak", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Laneko eremu honetan instalatutako aplikazioak {{$1}}", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Utzi lan-eremu hau", + "scenes.app.popup.appsparameters.pages.publication_description": "Zehaztu zure aplikazioaren ikusgarritasuna.", + "scenes.app.popup.appsparameters.pages.event_subtitle": "Gertaerak", + "scenes.app.channelsbar.modify_channel_menu": "Editatu kanala", + "scenes.app.channelsbar.read_sign": "Markatu irakurritako gisa", + "scenes.app.channelsbar.currentuser.collaborateurs": "Erabiltzaileak", + "scenes.app.channelsbar.currentuser.workspace_info": "{{$2}} taldeko {{$1}} lan eremuan zaude", + "scenes.login.home.email": "Posta elektronikoa", + "general.connexion_status.disconnected": "Lineaz kanpo zaude", + "scenes.login.home.title": "Hasi saioa Twake-n", + "scenes.app.integrations_parameters.title": "Integrazioak", + "scenes.app.integrations_parameters.applications_table.name": "Izena", + "scenes.app.integrations_parameters.applications_table.title": "Beste integrazio batzuk", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Bilatu aplikazioa", + "scenes.app.integrations_parameters.company_application_popup.tag": "Instalatua", + "scenes.app.integrations_parameters.company_application_popup.btn": "Instalatu", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Informazioak", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Deskribapena", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Webgunea", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Sortze data", + "application.load.longer": "Zerbitzariak uste baino denbora gehiago behar du erantzuteko, mesedez itxaron edo berriro kargatu orria...", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Mezuen haria", + "scenes.app.workspaces.create_company.group_data": "Konfiguratu zure talde berria", + "scenes.app.workspaces.create_company.group_data.group_type": "Talde mota", + "scenes.app.workspaces.create_company.group_data.group_type.company": "Enpresa edo enpresa saila", + "components.calendar.repetition.on": "On", + "components.calendar.repetition.after": "Ondoren", + "components.calendar.repetition.days": "eguna(k)", + "components.calendar.repetition.weeks": "astea(k)", + "components.calendar.repetition.months": "hilabetea(k)", + "components.calendar.repetition.years": "urtea(k)", + "components.calendar.repetition.occurrence": "Gertaera(k)", + "scenes.app.workspaces.create_company.group_data.title": "Azkar ibiliko gara; informazio estatistiko bat besterik ez dugu behar.", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Mezuen zenbakia", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "Twake-ren doako bertsioan, ezin duzu {{$1}} mezu berriagoak baino gehiago sartu.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Erakutsi plan gehiago", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "Eztabaida pribatu berria", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Ez dago mezu pribaturik. Gonbidatu erabiltzaileak!", + "scenes.app.channelsbar.channelsuser.private_messages": "Mezu zuzenak", + "scenes.app.channelsbar.channelsworkspace.channel_title": "KANALAK", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "GOGOKOOAK", + "scenes.app.channelsbar.channelsworkspace.create_channel": "Sortu kanal bat", + "scenes.app.channelsbar.channelsworkspace.no_channel": "Oraindik ez zara sartu inongo kanalean", + "scenes.app.channelsbar.guest_management": "Gonbidatuen kudeaketa", + "scenes.app.channelsbar.unread_sign": "Markatu irakurri gabeko gisa", + "scenes.app.channelsbar.channel_leaving": "Irten kanala", + "scenes.app.channelsbar.channel_removing": "Ezabatu kanala", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Kanal hauek zure negoziora inporta ditzakezu antolatuta egoteko marko honetan klik eginez.", + "scenes.app.channelsbar.company_invitation_alert_title": "Enpresara gonbidatuta zaude ", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "API ezarpenak", + "scenes.app.popup.appsparameters.pages.app_name_label": "Aplikazioaren izena", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Enpresa honetako kudeatzaile guztiek aplikazio hau editatu ahal izango dute.", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Definitu zure aplikazioak zer edita eta irakur dezakeen.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Aplikazio-pribilegioak", + "scenes.app.popup.appsparameters.pages.apps_title": "Zure aplikazioak eta konektoreak", + "scenes.app.popup.appsparameters.pages.automatique_label": "Automatikoa", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "'Automatiko' aktibatzen baduzu, aplikazio hau automatikoki gehituko da enpresa honen hurrengo lan-eremuetan.", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "Baimendutako IP helbideak", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "Zure aplikazioaren argitalpena Twake taldeak baliozkotzeko zain dago.", + "scenes.app.popup.appsparameters.pages.button_force": "Indarra enpresa osoan", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "'{{$1}}' eta '{{$2}}' id motako gertaera '{{$3}}' pasiboekin", + "scenes.app.popup.appsparameters.pages.company_label": "Enpresaren jabea", + "scenes.app.popup.appsparameters.pages.configuration_label": "Konfigurazioa", + "scenes.app.popup.appsparameters.pages.create_app_button": "Sortu aplikazio bat", + "scenes.app.popup.appsparameters.pages.create_my_app": "Sortu nire aplikazioa", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Oraindik ez duzu aplikaziorik sortu. Aplikazio edo konektore bat sortu aurretik, ziurtatu ez dagoela gure aplikazioen merkatuan.", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "Ezabatu aplikazioa", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Zure aplikazioa non ikusgai egongo den definitzeko aukera ematen du.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Bistaratzeko ezarpenak", + "scenes.app.popup.appsparameters.pages.error_user_code": "akatsa", + "scenes.app.popup.appsparameters.pages.ok_user_code": "Ados", + "scenes.app.popup.appsparameters.pages.optimal_format": "Formatu optimoa: 48x48px.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "Argitaratu gabeko aplikazioak zure enpresan bakarrik funtzionatuko du. Twake-ren erabiltzaile guztientzat erabilgarri jarri nahi baduzu, aktibatu aukera hau.", + "scenes.app.popup.appsparameters.pages.public_availability_application": "Eskaera publikoa", + "scenes.app.popup.appsparameters.pages.public_login_label": "Identifikatzaile publikoa", + "scenes.app.popup.appsparameters.pages.publication_label": "Argitalpena", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Argitaratu aplikazioa", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Irakurri pribilegioak", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Kendu enpresa osotik", + "scenes.app.popup.appsparameters.pages.status_tilte": "Estatu", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode probatzailea", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "Gertaeren harreraren URLa", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "Zain...", + "scenes.app.popup.appsparameters.pages.website_label": "Webgunea", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Idatzi pribilegioak", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Errore bat gertatu da aplikazioa eguneratzean.", + "scenes.app.popup.appsparameters.pages.remove_app_button": "Ezabatu aplikazioa", + "scenes.app.popup.appsparameters.pages.update_button": "Eguneratu", + "scenes.app.popup.createworkspacepage.add_subtitle": "Leku gehiago behar duzu?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Sortu lan-eremu berri bat", + "scenes.app.popup.userparameter.pages.notif_content_label": "Jakinarazpenen edukia", + "scenes.app.mainview.quick_search_placeholder": "Bilaketa azkarra", + "scenes.app.popup.workspaceparameter.admin_current_status": "Administratzailea zara.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Enpresaren administratzailea zara.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Ezabatu lan-eremua", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Laneko eremuan bakarrik egon behar zara kentzeko. Kendu kolaboratzaileak eta saiatu berriro.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Lan-eremu hau ezabatu nahi duzula berresteko, idatzi beheko izena eta sakatu Ezabatu.", + "scenes.app.popup.workspaceparameter.pages.enter": "Sartu ", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Laneko moderatzailea", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Ezin duzu lan-eremutik irten, azken administratzailea zarelako. Administratzaile berri bat defini dezakezu edo lan-eremu hau ezabatu/artxibatu dezakezu.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Aplikazio guztiak", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Zure enpresaren aplikazioak", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Bilatu aplikazioak", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Lan-eremu honen aplikazioak", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Itzuli bilaketara", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Enpresako beste eremu batzuetan instalatutako aplikazioak {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Instalatutako aplikazioak", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Errore bat gertatu da erabiltzaile hauek gonbidatzean: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Egiaztatu erabilitako erabiltzaile-izena edo posta elektronikoa baliozkoa dela.", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Editatu lan-eremu honen irudia", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Logotipoa", + "scenes.app.popup.workspaceparameter.pages.name_description": "Aldatu lan-eremu honen izena", + "scenes.app.popup.workspaceparameter.pages.no_access": "Sarbiderik ez.", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "Ez duzu aplikaziorik lan-eremu honetan", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Irakurtzeko sarbidea", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Kendu enpresa osotik", + "scenes.app.popup.workspaceparameter.pages.research_by": "Bilatu aplikazioak izenaren eta kategorien arabera", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Webhooketarako sarbidea", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Gehienezko tamaina 5 MB.", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Kendu lan-eremu honetatik", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "lan-eremua", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Idazteko sarbidea", + "scenes.apps.messages.message.pin_button": "Ainguratu mezua", + "scenes.apps.messages.message.unpin_button": "Kendu mezua", + "scenes.apps.messages.message.copy_link": "Kopiatu esteka mezurako", + "scenes.apps.messages.message.pinned": "Ainguratuta", + "scenes.apps.messages.message.remove_button": "Ezabatu", + "scenes.apps.messages.message.reply_button": "Erantzun", + "scenes.apps.messages.message.save_button": "Gorde", + "scenes.apps.messages.message.show_button": "Bistaratzea", + "scenes.apps.messages.message.show_responses_button": "Ikusi erantzun guztiak", + "scenes.apps.messages.message.types.first_channel_message_text": "Hau da kanalaren lehen mezua", + "scenes.apps.messages.message.types.first_message_text": "Hau da lehen mezua", + "scenes.apps.messages.messageslist.get_writing_user": "idazten ari da...", + "scenes.apps.messages.messageslist.get_writing_users": "idazten ari dira...", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Mezu berriak", + "scenes.error_on_twake": "\"Houston arazo bat dugu\"", + "scenes.help_us": "Hala ere, errore hau konpontzen lagundu nahi badiguzu, bidali mezu bat behean: ", + "scenes.login.verifymail.alert": "Zure e-maila egiaztatzen ari gara!", + "scenes.login.verifymail.error_message": "Akats bat gertatu da", + "scenes.login.verifymail.signin_button": "Saioa hasi", + "scenes.login.verifymail.success": "Zure e-posta behar bezala egiaztatu da!", + "scenes.login.verifymail.verification_waiting": "Egiaztapenaren zain...", + "services.apps.calendar.deadline_icon": "Epemuga", + "services.apps.calendar.event_icon": "Gertaera", + "services.apps.calendar.reminder_icon": "Oroigarria", + "services.apps.messages.no_app": "Aplikazio hau ez da existitzen.", + "services.apps.messages.no_command_possible": "Ezin dugu '{{$1}}' komandoa exekutatu '{{$2}}' ez delako existitzen edo ez duelako komandoak sortzeko aukera ematen.", + "services.user.notification_parameters_update_alert": "Jakinarazpenen ezarpenak eguneratu dira.", + "services.user.update_password_alert": "Zure pasahitza eguneratu da.", + "scenes.apps.calendar.unconfigured_tab": "Fitxa hau ez dago konfiguratuta oraindik.", + "scenes.apps.drive.top_menu_more": "Gehiago", + "scenes.apps.drive.top_menu_no_items": "{{$1}} elementuak", + "scenes.apps.messages.new_thread": "Hasi eztabaida berri bat", + "scenes.apps.account.account.save": "Gorde kontua", + "scenes.apps.account.message_user_signin": "Zure erabiltzaileak edonoiz hasi dezake saioa e-posta bera erabiliz eta behin-behineko kontua kontu arrunt batera alda dezake.", + "scenes.app.mainview.link_expired": "Esteka publiko hau baliogabea da edo iraungi egin da.", + "scenes.app.mainview.create_account": "Sortu zure lan-eremua doan ", + "scenes.apps.calendar.modals.reminder_add": "Gehitu abisua", + "scenes.apps.parameters.workspace_sections.members.invite_all": "Gonbidatu guztiak", + "scenes.app.taskpicker.select": "Hautatu", + "scenes.apps.tasks.no_connector": "Ez dago konektorerik", + "components.attachmentpicker.add_attachment": "Gehitu eranskinak", + "components.input.copied": "Kopiatua", + "components.drive.navigators.directory_not_found": "Direktorioa ez da aurkitu.", + "components.drive.right_preview.suppress_link": "Ezabatu esteka", + "components.drive.right_preview.create_link": "Sortu sarbide-esteka bat", + "components.drive.moove_here": "Mugitu hona", + "components.drive.modify_uslist": "Erabiltzaileen zerrenda aldatu", + "components.tagpicker.tag_name": "Etiketa izena", + "components.searchpopup.only_pinned": "Ainguratutako mezuak soilik", + "components.alert.confirm": "Berretsi zure ekintza", + "components.alert.confirm_click": "Berretsi zure ekintza Ados sakatuz.", + "components.searchpopup.tasks": "Zereginak", + "scenes.app.mainview.advanced_search_placeholder": "Bilaketa aurreratua", + "components.searchpopup.hide_filters": "iragazkiak ezkutatu", + "components.searchpopup.show_filters": "iragazkiak erakutsi", + "components.searchpopup.load_more": "Kargatu emaitza gehiago", + "general.more": "Gehiago", + "scenes.apps.board.archived_tasks": "Artxibatutako zereginak ({{$1}})", + "scenes.apps.board.active_tasks": "Zeregin aktiboak", + "scenes.apps.board.new_task": "+ Zeregin berria", + "scenes.apps.board.all_boards": "Batzorde guztiak", + "components.userlistmanager.no_users": "Erabiltzailerik ez.", + "components.reminder.minutes_bef": "minutu lehenago", + "services.console_services.toaster.success_invite_emails": "Gehitu dira {{$1}} erabiltzaile(k)", + "scenes.client.channels_bar.modals.guest_management.title": "Kudeatu gonbidatuak {{$1}}-n", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Bilatu gonbidatuak edo zain dauden mezu elektronikoak", + "scenes.client.channels_bar.modals.guest_management.tips": "Hasi mezu elektronikoak gehitzen edo bilatzen goiko sarrera erabiliz", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Bidalitako posta", + "general.user.role.company.admin": "Enpresako administratzailea", + "general.user.role.company.guest": "Gonbidatua", + "general.user.deleted": "Ezabatutako kontua", + "components.richtexteditor.toolbar.bold": "Lodia", + "components.richtexteditor.toolbar.underline": "Azpimarratu", + "components.richtexteditor.toolbar.italic": "Etzana", + "components.richtexteditor.toolbar.strikethrough": "Markatua", + "components.richtexteditor.toolbar.code": "Kodea", + "components.richtexteditor.toolbar.unordered-list": "Buletaren zerrenda", + "components.richtexteditor.toolbar.ordered-list": "Zerrenda ordenatua", + "components.richtexteditor.toolbar.blockquote": "Blokeoa", + "components.richtexteditor.toolbar.code-block": "Kode blokea", + "components.locked_features.locked_history_banner.title": "Mezuen mugara iritsi berri zara", + "components.locked_features.locked_history_banner.description": "Zure enpresak mezu asko ditu! Berritu orain zure mezuen historia guztia atzitzeko.", + "components.locked_features.locked_history_banner.button": "Gehiago ikasi", + "components.locked_features.locked_guests_popup.subtitle": "Ezaugarri hau ez dago eskuragarri Twake doako bertsioan", + "components.locked_features.locked_guests_popup.description": "Aupa!! Kanpoko erabiltzaileak zure laneko gunera gonbidatu nahi dituzula dirudi. Baliteke zure plana berritzea kontuan hartu nahi izatea gonbidatuekin eta kanpoko bazkideekin elkarlanean aritu nahi baduzu. Arakatu gure prezio-aukerak eta hautatu aukerarik onena zure taldeko lankidetza-beharretarako.", + "components.locked_features.locked_guests_popup.learn_more_button": "Gehiago ikasi", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Saltatu orain", + "components.locked_features.locked_guests_popup.or": "Edo", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Arazo bat dago zure enpresaren harpidetzarekin. Mesedez, begiratu zureari", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Arazo bat dago zure enpresaren harpidetzarekin. Mesedez, jarri harremanetan enpresaren jabearekin edo administratzailearekin!", + "components.on_boarding.popups.blocked_company.description": "Twake-rako harpidetza iraungi da. Mesedez, jarri harremanetan zure enpresaren jabearekin edo administratzailearekin hura berritzeko eta zure taldearekin berriro komunikatu ahal izateko!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Enpresen harpidetza-planari buruz gehiago jakin nahi duzu?", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Klikatu hemen", + "components.on_boarding.popups.blocked_company.or": "Edo", + "components.on_boarding.popups.blocked_company.company_selector": "Aldatu beste enpresa batera", + "scenes.apps.tasks.select_user_button": "Ikusi beste erabiltzaile baten zereginak", + "scenes.apps.tasks.select_user": "Bilatu erabiltzailea", + "scenes.apps.messages.input.attach_file.from_computer": "Ordenagailutik", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}}-ek bere mezua ezabatu du", + "components.member.user_parts.and_more_user_text": " eta {{$1}} erabiltzaile gehiago", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Sortu kanal pribatu bat", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " horren ordez", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Ezin duzu 10 erabiltzaile baino gehiago gehitu", + "general.uploading": "Kargatzen", + "components.upload.drop_files.toaster.error": "Ezin duzu {{$1}} fitxategi baino gehiago kargatu", + "components.emoji_picker.categories.frequently_used": "Maiz erabiltzen da", + "components.emoji_picker.categories.smileys_and_people": "Irribarreak eta jendea", + "components.emoji_picker.categories.animals_and_nature": "Animaliak eta Natura", + "components.emoji_picker.categories.food_and_drink": "Janaria eta edaria", + "components.emoji_picker.categories.activity": "Jarduera", + "components.emoji_picker.categories.travel_and_places": "Bidaiak eta Lekuak", + "components.emoji_picker.categories.objects": "Objektuak", + "components.emoji_picker.categories.symbols": "Sinboloak", + "components.emoji_picker.categories.flags": "Banderak", + "components.emoji_picker.categories.search_result": "Bilaketa-emaitzak", + "components.emoji_picker.categories.not_found": "Ez da emojirik aurkitu", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Rola", + "general.email": "Posta elektronikoa", + "components.locked_features.locked_workspace_popup.title": "Ezin duzu lan-eremu gehiago sortu", + "components.locked_features.locked_workspace_popup.text": "Aupa!! Zure enpresan lan-eremu berri bat sortu nahi duzu? Baliteke plana berritzea kontuan hartu nahi izatea. Arakatu gure prezio-aukerak eta hautatu aukerarik onena zure taldeko lankidetza-beharretarako.", + "components.locked_features.locked_only_office_popup.text": "Aupa!! Twake-tik fitxategia editatu nahi duzula dirudi. Baliteke zure plana berritzea kontuan hartu nahi izatea bulegoko fitxategien inguruan elkarlanean aritu nahi baduzu. Arakatu gure prezio-aukerak eta hautatu aukerarik onena zure taldeko lankidetza-beharretarako.", + "components.locked_features.locked_drive_popup.title": "Gidatzeko mugara iritsi berri zara", + "components.locked_features.locked_drive_popup.subtitle": "Doako bertsioan, 6GB bakarrik gorde ditzakezu.", + "general.resume": "Jarraitu", + "general.pause": "Etenaldia", + "\"": "\"", + "login.create_account": "Kontua sortu", + "login.login_error": "Errorea saioa hastean", + "'": "'", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Inork ez zaitu laneko gune batera gonbidatu oraindik.", + "scenes.apps.messages.message.types.no_message_in_thread": "Oraindik inork ez zuen erantzun.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Lan-eremu lehenetsia", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Gonbidatu automatikoki laneko erabiltzaile guztiak kanal honetara", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "{{$1}} ezabatzera zoaz", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Oraindik {{$1}} kideak dituzu {{$2}}-n. Kide guztiak kendu behar dituzu lan-eremu hau ezabatu ahal izateko.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Ulertzen dut nire lan-eremuko mezu eta fitxategi guztiak ezabatuko direla.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Gehienezko logotipoaren tamaina 5 MB da", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Formatu txarra, png gif eta jpg bakarrik onartzen dira", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Errore ezezaguna", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Errorea", + "scenes.app.channelsbar.currentuser.reset": "Berrezarri", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Idatzi gutxienez hiru letra erabiltzaileak erakusteko", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Ez da erabiltzailerik aurkitu", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Ez da emojirik aurkitu", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Ez da komandorik aurkitu", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} idazten ari da...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} eta {{$2}} idazten ari dira...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} eta {{$3}} erabiltzaile gehiago idazten ari dira...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Zure enpresak {{$1}} kideen gehienezko mugara iritsi da. Mesedez ", + "components.locked_features_components.locked_invite_alert.message_link": "berritu zure enpresa", + "components.locked_features_components.locked_invite_alert.message_part_2": " kide gehiago gonbidatzeko.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " jarri harremanetan zure enpresaren jabearekin edo administratzailearekin.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Ikusi nire konpainiako kide guztiak kontsolan", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Deskribatu zure aplikazioa hitz gutxitan", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Integrazio berria", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Ulertzen dut enpresa honen jabeak eta administratzaileak aplikazio hau aldatu eta argitaratu ahal izango dutela.", + "twake.application.access.title": "Hautatu zure aplikaziorako esparru egokiak.", + "twake.application.access.no_default_scopes_available'": "Integrazio honek ez du {{$1}} sarbiderik", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake APIaren dokumentazioa", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Hauek nola bete ez badakizu, joan hona ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Gako pribatua", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Behar bezala kendu da aplikazioa {{$1}}!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Errore bat gertatu da {{$1}} aplikazioa kentzean!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Arrakastaz {{$1}} aplikazioa!", + "scenes.app.integrations_parameters.add_application": "Integrazio berria", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Garatzaileen ezarpenak", + "components.rich_text_editor.plugins.suggestions.loading": "Gehiagoren bila", + "components.open_desktop_popup.subtitle": "Twake aplikazioan ireki da", + "components.open_desktop_popup.open_here_link": "Ireki hemen ordez", + "molecules.download_banner.title": "Atera etekinik handiena Twake-ri, deskargatu mahaigaineko aplikazioa orain", + "molecules.download_banner.download_button": "Deskargatu mahaigaineko aplikazioa", + "scenes.app.channelsbar.channel_copy_link": "Kopiatu kanalaren esteka", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Behar bezala eguneratu da", + "components.searchpopup.no_results_for": "Ez zen emaitzarik izan", + "components.searchpopup.try_new_search": "Saiatu bilaketa berri bat", + "components.searchpopup.all": "Denak", + "components.searchpopup.chats": "Txatak", + "components.searchpopup.media": "Komunikabideak", + "components.searchpopup.files": "Fitxategiak", + "components.searchpopup.recent_chats": "Azken txatak", + "components.searchpopup.recent_media": "Azken komunikabideak", + "components.searchpopup.recent_files": "Azken fitxategiak", + "components.searchpopup.recent_channels_and_contacts": "Azken kanalak eta kontaktuak", + "components.searchpopup.header_title": "Bilatu", + "components.searchpopup.scope.company": "konpainia guztietan", + "components.searchpopup.scope.channel": "kanal honetan", + "components.searchpopup.channels": "Kanalak", + "components.searchpopup.messages": "Mezuak" +} diff --git a/twake/frontend/public/locales/fi.json b/twake/frontend/public/locales/fi.json index bd5a295f1a..f365f34008 100644 --- a/twake/frontend/public/locales/fi.json +++ b/twake/frontend/public/locales/fi.json @@ -422,5 +422,489 @@ "components.emoji_picker.categories.food_and_drink": "Ruoka ja juoma", "general.user.role.company.admin": "Yrityksen ylläpitäjä", "components.emoji_picker.categories.search_result": "Hakutulokset", - "components.emoji_picker.categories.not_found": "Emojia ei löytynyt" -} \ No newline at end of file + "components.emoji_picker.categories.not_found": "Emojia ei löytynyt", + "scenes.app.popup.adduser.magiclinks.action_generate": "Tuottaa", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Et ole vielä luonut sovellusta. Ennen kuin luot sovelluksen tai liittimen, varmista, ettei sitä ole jo olemassa sovellusmarkkinoillamme.", + "scenes.app.popup.appsparameters.pages.publication_description": "Määritä sovelluksesi näkyvyys.", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Poista koko yrityksestä", + "scenes.app.popup.appsparameters.pages.show_button": "Näytä", + "scenes.app.popup.appsparameters.pages.status_tilte": "Osavaltio", + "scenes.app.popup.appsparameters.pages.string_information": "Tämä merkkijono identifioi sovelluksesi ja sitä käytetään viestikomennoissa.", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode-testeri", + "scenes.app.integrations_parameters.applications_table.name": "Nimi", + "scenes.app.integrations_parameters.applications_table.title": "Muut integraatiot", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Hakusovellus", + "scenes.app.integrations_parameters.company_application_popup.tag": "Asennettu", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Verkkosivusto", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Luomispäivä", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Versio", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Näytä", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Poista yhtiöstä", + "scenes.app.integrations_parameters.company_applications_table.name": "Nimi", + "scenes.apps.messages.input.replied_to": "vastasi ", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "Kiinteistöt", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "Kemia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Kauppa / Kauppa / Jakelu", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Kustannustoiminta / Viestintä / Multimedia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Elektroniikka / Sähkö / Energia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Opintoja ja neuvoja", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "Lääketeollisuus", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "IT / Telecom", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Koneet / Autot", + "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "Liikepalveluja", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Viihde", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "Tekstiilit / Vaatteet / Kengät", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Kuljetus / Logistiikka", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Tutkimus", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "koulutus", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Hallinto", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "muu", + "scenes.apps.tasks.list_modal.modify_list": "Muokkaa listaa", + "scenes.apps.tasks.list_modal.new_list": "Uusi lista", + "scenes.apps.tasks.list_modal.remove": "Poista luettelo ja tehtävät", + "scenes.apps.tasks.list_modal.predefined_participants": "Ennalta määrätyt osallistujat", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Poista arkistoidut tehtävät ({{$1}})", + "scenes.app.workspaces.welcome_page.create_my_company": "Luo yritykseni", + "scenes.app.workspaces.welcome_page.lets_go": "Mennään!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Kutsuttiinko sinut toisella sähköpostiosoitteella?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Voi, no... Näyttää siltä, ettei kukaan ole vielä kutsunut sinua työtilaan.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Olet nyt valmis työskentelemään.", + "components.calendar.repetition.months": "kuukaudet)", + "components.calendar.repetition.years": "vuosi(t)", + "components.calendar.repetition.custom_recurrence": "Mukautettu toistuminen", + "components.calendar.repetition.occurrence": "Tapahtuma(t)", + "components.calendar.repetition.repeat_on": "Toista", + "scenes.app.channelsbar.currentuser.add_apps": "Hae sovelluksia", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Vahvista, että haluat poistaa tämän työtilan, kirjoita nimi alle ja paina Poista.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Kutsulinkki työtilaan", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Uusi linkki luotu", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Kopiointi leikepöydälle onnistui", + "scenes.app.popup.adduser.magiclinks.action_copy": "Kopio", + "scenes.app.popup.appsparameters.pages.publication_label": "Julkaisu", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Julkaise hakemus", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Lukuoikeudet", + "scenes.app.popup.appsparameters.pages.remove_app": "Poista sovellus {{$1}} pysyvästi.", + "components.drive.moove_here": "Muuta tänne", + "components.drive.modify_uslist": "Muokkaa käyttäjäluetteloa", + "components.tagpicker.tag_name": "Merkin nimi", + "components.searchpopup.only_pinned": "Vain kiinnitetyt viestit", + "components.searchpopup.tasks": "Tehtävät", + "scenes.app.mainview.advanced_search_placeholder": "Tarkennettu Haku", + "scenes.app.integrations_parameters.title": "Integraatiot", + "scenes.app.integrations_parameters.company_application_popup.btn": "Asentaa", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Tiedot", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Kuvaus", + "scenes.app.integrations_parameters.company_applications_table.title": "Asennettu yritykseesi", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "{{$1}} poistettiin onnistuneesti yrityksestäsi", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "{{$1}} lisätty yritykseesi", + "scenes.join.loading": "Ladataan…", + "scenes.join.wrong_link_title": "Tämä linkki ei ole enää saatavilla", + "scenes.join.wrong_link_description": "Pyydä henkilöltä, joka kutsui sinut tähän yritykseen, uusi linkki tai luo oma yritys", + "scenes.join.create_the_company_button": "Luo yritys", + "scenes.join.join_workspace_from_company": "Liity {{$1}}:ään {{$2}}:stä!", + "scenes.join.twake_description": "Twake on avoimen lähdekoodin digitaalinen työtila, joka on suunniteltu parantamaan tiimisi tuottavuutta", + "scenes.join.login_first_button": "Kirjaudu sisään tai luo ensin tili", + "scenes.join.join_the_team_button": "Liity joukkueeseen", + "general.archive": "Arkisto", + "general.unarchive": "Poista arkistosta", + "application.load.longer": "Palvelimella kestää odotettua kauemmin vastata, odota tai lataa sivu uudelleen...", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Viestiketju", + "scenes.app.workspaces.create_company.group_data.group_type.company": "Yritys tai yrityksen osasto", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Seura, klubi tai hyväntekeväisyysjärjestö", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "Pääaktiviteetti", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Ruokaa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "Pankki / vakuutus", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Tulostus / Paperi", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "Rakentaminen / Rakennusmateriaalit", + "scenes.apps.calendar.calendar.list_btn": "Lista", + "scenes.apps.calendar.event_edition.title_confidentiality": "Luottamuksellisuus", + "scenes.apps.calendar.event_view.article_until": "kohtaan", + "scenes.apps.drive.navigators.navigator_labels.title": "Tarrat", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} ja {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "Vain {{$1}}", + "scenes.apps.account.title": "Tilin parametrit", + "scenes.apps.account.notifications.keywords_placeholder": "kehittäjä, wifi, koodi, ...", + "scenes.apps.account.notifications.disturb_option_a": "Älä lähetä minulle push-ilmoituksia välillä ", + "scenes.apps.account.notifications.disturb_option_b": " ja ", + "scenes.apps.account.notifications.disturb_option_c": " (paikallinen aikavyöhyke)", + "scenes.apps.account.notifications.devices_option_ever": "Lähetä minulle aina push-ilmoituksia", + "scenes.apps.account.notifications.devices_option_inactive": "Lähetä minulle push-ilmoituksia, kun en ole aktiivinen työpöydällä", + "scenes.apps.account.notifications.devices_option_never": "Älä koskaan lähetä minulle push-ilmoituksia", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Laajennus", + "scenes.apps.parameters.workspace_sections.members.pending": "Odottavat sähköpostit", + "scenes.apps.tasks.no_connectors_menu_text": "Sinulla ei ole liittimiä, jotka voisivat muodostaa yhteyden kalenteriin.", + "scenes.apps.tasks.boards": "Taulut", + "scenes.apps.tasks.connectors_menu": "Liittimet...", + "scenes.apps.tasks.connectors_search_menu": "Hae liittimiä...", + "scenes.apps.tasks.unconfigured_tab": "Tätä välilehteä ei ole vielä määritetty.", + "scenes.apps.tasks.choose_board_button": "Valitse taulu", + "scenes.apps.tasks.new_board.title": "Uusi lauta", + "scenes.apps.tasks.new_board.edit_title": "Muokkaa taulua", + "scenes.apps.tasks.task": "Tehtävä", + "scenes.apps.tasks.task_status.todo": "Tehdä", + "scenes.apps.tasks.task_status.current": "Nykyinen", + "scenes.apps.tasks.task_status.done": "Tehty", + "scenes.apps.tasks.task.assignees": "Valtuutetut", + "scenes.apps.tasks.task.edit.dates": "Päivämäärät", + "scenes.login.footer.go_to_twake": "Siirry osoitteeseen twakeapp.com", + "scenes.login.footer.branding": "Olet {{$1}} ({{$2}}) yksityisellä Twake-palvelimella. ", + "scenes.login.create_account.fill_in_email": "Sinun tulee täyttää sähköpostisi oikealla sähköpostiosoitteella", + "scenes.login.forgot_password.text2": "Saat 9-numeroisen koodin. Kirjoita se alla olevaan kenttään jatkaaksesi.", + "scenes.login.forgot_password.password_dont_match": "Salasanasi eivät täsmää tai ne ovat liian lyhyitä. Kirjoita salasana, jossa on vähintään 8 merkkiä.", + "scenes.app.workspaces.create_company.company_name.title_1": "Aloittaa,", + "scenes.app.workspaces.create_company.company_name.title_2": "ilmoittaa yrityksesi nimi.", + "scenes.app.workspaces.create_company.default_workspace_name": "Main", + "scenes.app.workspaces.create_company.importations.title_1": "Työskenteletkö jo digitaalisten työkalujen kanssa? Tuo tai integroi työkalusi nyt!", + "scenes.app.workspaces.create_company.importations.title_2": "Ei hätää, voit tehdä tämän myöhemmin!", + "scenes.app.workspaces.welcome_page.added_to_company": "Sinut on kutsuttu ", + "scenes.app.workspaces.create_company.group_data.title": "Toimimme nopeasti – tarvitsemme vain tilastotietoja.", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Lähetimme sinulle vahvistuskoodin {{$1}}:n kautta", + "scenes.apps.account.account.description_main": "Pääosoitteesi on paikka, johon Twake lähettää ilmoituksesi. Toissijaisten osoitteiden avulla sinut kutsutaan automaattisesti niitä käyttäviin työtiloihin.", + "scenes.apps.account.identity.description": "Muuta etunimesi, sukunimesi ja profiilikuvasi, joka näkyy muille Twaken käyttäjille.", + "components.calendar.repetition.weekly_on": "Viikoittain {{$1}}", + "components.calendar.repetition.monthly_on": "Kuukausittain {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Kuukausittain päivänä {{$1}}", + "components.calendar.repetition.annually_on": "Vuosittain {{$1}}", + "components.calendar.repetition.every_weekday": "Joka arkipäivä (ma-pe)", + "components.calendar.repetition.repeat": "Toista joka", + "components.calendar.repetition.on": "Päällä", + "components.calendar.repetition.after": "Jälkeen", + "components.calendar.repetition.days": "päivä(t)", + "components.calendar.repetition.weeks": "viikko(t)", + "scenes.app.channelsbar.currentuser.workspace_info": "Olet työtilassa {{$1}} ryhmästä {{$2}}", + "scenes.app.channelsbar.currentuser.update": "Päivittää", + "scenes.app.channelsbar.currentuser.disable_notifications": "Poista käytöstä", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Pois käytöstä 1h", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Pois käytöstä klo 9 asti. huomenna", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Aktivoi uudelleen", + "scenes.app.channelsbar.channelsuser.private_messages": "Suorat viestit", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Voit tuoda nämä kanavat yritykseesi pysyäksesi järjestyksessä napsauttamalla tätä kehystä.", + "scenes.app.channelsbar.initial_instructions_tutorial": "Valitse etunimi, nimi ja profiilikuva.", + "scenes.app.channelsbar.welcoming_message_subtitle": "Ryhdy Twake-ammattilaiseksi muutamalla napsautuksella!", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Sinulla ei ole liitintä, joka voi muodostaa yhteyden kanavaan.", + "scenes.app.popup.adduser.adresses_message": "Erota osoitteet pilkulla tai välilyönnillä. Muista, että Twake voi rajoittaa kutsujen määrää tilauksesi perusteella.", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Testaa Twacode-viestiesi ulkoasua", + "scenes.app.channelsbar.company_invitation_alert_title": "Sinut on kutsuttu yritykseen ", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Kaikki tämän yrityksen johtajat voivat muokata tätä sovellusta.", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Määritä, mitä sovelluksesi voi muokata ja lukea.", + "scenes.app.popup.appsparameters.pages.app_update": "Päivitä sovellus {{$1}} (sovellusta käytetään {{$2}} kertaa.)", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "Jos aktivoit \"Automaattinen\", tämä sovellus lisätään automaattisesti tämän yrityksen seuraaviin työtiloihin.", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "Hakemuksesi julkaisu odottaa tällä hetkellä Twake-tiimin vahvistusta.", + "scenes.app.popup.appsparameters.pages.button_force": "Voimia koko yrityksessä", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "Tapahtuman tyyppi {{$1}} ja tunnus {{$2}} passiivisilla merkinnöillä {{$3}}", + "scenes.app.popup.appsparameters.pages.installation": "Asentaa.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Aloita kirjoittamalla viestisi JSON-muodossa.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Sisäinen sovellus", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Siirry dokumentaatioon luodaksesi määritykset JSON-muodossa.", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Passiivinen data, joka lähetetään seuraavassa tapahtumassa", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Muokkaa sovelluksesi julkisia tietoja.", + "scenes.app.popup.appsparameters.pages.ok_user_code": "okei", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Aseta mobiili-ilmoitusten tiheys.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Ilmoitusten tiheys", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Korosta seuraavat avainsanat:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Aseta sähköposti-ilmoitusten tiheys.", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Valitse ajanjakso, jonka aikana et saa ilmoituksia.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Älä häiritse yöllä", + "scenes.app.popup.userparameter.pages.notif_content_label": "Ilmoitusten sisältö", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Muuta tämän yrityksen nimi", + "scenes.app.popup.workspaceparameter.pages.show_button": "Näyttö", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Pääsy webhookeihin", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Poista tästä työtilasta", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "työtila", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Kirjoitusoikeus", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Sinun sovelluksesi", + "scenes.app.workspacesbar.components.change_company_title": "Vaihda yritystä", + "scenes.app.workspacesbar.components.create_company_menu": "Luo yritys", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} asetukset", + "scenes.apps.calendar.connectors_search_menu": "Hae liittimiä...", + "scenes.apps.calendar.no_calendar_text": "Et ole asettanut kalentereita tälle työtilalle.", + "scenes.apps.calendar.no_connectors_menu_text": "Sinulla ei ole liittimiä, jotka voisivat muodostaa yhteyden kalenteriin.", + "scenes.apps.calendar.remove_calendar_confirmation": "Poistetaanko kalenteri ja sen tapahtumat pysyvästi?", + "scenes.apps.drive.no_file_alert": "Sinulla ei ole sovelluksia, joiden avulla voit luoda tiedoston.", + "scenes.apps.drive.no_storage_app_alert": "Sinulla ei ole sovelluksia, joiden avulla voit lisätä ulkoista tallennustilaa.", + "scenes.apps.drive.trash_empty_menu": "Tyhjennä roskakori", + "scenes.apps.drive.unconfigured_tab": "Tätä välilehteä ei ole vielä määritetty.", + "scenes.apps.drive.viewer.edit_with_button": "Muokkaa käyttämällä {{$1}}", + "scenes.apps.messages.input.placeholder": "Kirjoittaa viestin. Käytä @ lainataksesi käyttäjää.", + "scenes.apps.messages.message.show_button": "Näyttö", + "scenes.apps.messages.message.show_responses_button": "Katso kaikki vastaukset", + "scenes.apps.messages.messageslist.get_writing_user": "kirjoittaa...", + "scenes.apps.messages.messageslist.get_writing_users": "kirjoittavat...", + "scenes.apps.messages.messageslist.go_last_message_button": "Siirry viimeiseen viestiin", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Uusia viestejä", + "scenes.error_on_twake": "\"Houston, meillä on ongelma\"", + "scenes.help_us": "Jos kuitenkin haluat auttaa meitä korjaamaan tämän virheen, lähetä meille viesti alla: ", + "scenes.login.verifymail.alert": "Tarkistamme sähköpostisi!", + "scenes.no_panic": "Älä panikoi! Korjaa Twake lataamalla tämä sivu uudelleen.", + "services.apps.calendar.reminder_icon": "Muistutus", + "services.apps.messages.no_app": "Tätä sovellusta ei ole olemassa.", + "services.apps.messages.no_command_possible": "Emme voi suorittaa komentoa \"{{$1}}\", koska \"{{$2}}\" ei ole olemassa tai se ei salli komentojen luomista.", + "scenes.apps.calendar.unconfigured_tab": "Tätä välilehteä ei ole vielä määritetty.", + "scenes.tell_us": "Kerro meille mitä olit tekemässä:", + "scenes.apps.drive.viewer.download_desktop": "Lataa Twake Desktop esikatsellaksesi sovelluksessa", + "scenes.apps.tasks.my_tasks": "Minun tehtäväni", + "scenes.apps.tasks.board.place_holder": "Hallituksen nimi", + "scenes.apps.tasks.board.tasks.use_deadline": "Käytä määräaikaa", + "scenes.apps.tasks.board.tasks.use_starttime": "Käytä aloitusaikaa", + "scenes.apps.tasks.board.tasks.in_list": "Luettelossa", + "scenes.apps.tasks.board.starts": "Aloittaa", + "scenes.apps.tasks.board.ends": "Tehtävää varten", + "scenes.apps.tasks.board.list_name": "Listanimi", + "scenes.app.popup.sync_calendar": "Synkronoi kalenterisi.", + "components.searchpopup.filter_ws": "Suodata työtilat", + "components.searchpopup.tags": "Tunnisteet", + "components.searchpopup.update_search": "Päivitä haku", + "scenes.apps.drive.remove_attachs": "Poista liitteet", + "components.drive.elements.see": "Katso", + "scenes.apps.drive.right_preview.public": "Julkinen pääsy", + "components.drive.elements.configurate_mod": "Määritä mode...", + "components.drive.elements.manage_version": "Hallitse versioita", + "scenes.apps.tasks.active_tasks": "aktiivisia tehtäviä", + "scenes.apps.drive.right_preview.versions": "Versiot", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Hallitse sovelluksiasi ja liittimiäsi.", + "scenes.app.popup.appsparameters.pages.icon": "Kuvake", + "scenes.app.popup.appsparameters.pages.title_informations": "Perustiedot", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Sovellusten hallintaan liittyvät tiedot", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} sähköpostiosoitetta lisätään", + "components.newversion.new_version_component.row.part_2": "Suosittelemme lataamaan sovelluksen uudelleen ja nauttimaan uusista ominaisuuksistamme!", + "components.newversion.new_version_component.link": "Napsauta tätä ladataksesi uudelleen", + "components.inputs.input_with_select.select.placeholder": "Osion nimi", + "components.inputs.input_with_select.select.no_sections": "Aloita ensimmäisen kanavaosiosi nimen kirjoittaminen.", + "components.inputs.input_with_select.button.tooltip": "Aseta kanavaosio", + "components.add_mails_workspace.button": "Aloita Twaken käyttö", + "components.add_mails_workspace.title_1": "Lisää käyttäjiä", + "components.add_mails_workspace.title_2": "Twake on tiimin yhteistyötyökalu, joten kutsu joitain käyttäjiä testaamaan sinulle luomaamme työtilaa.", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Ohita nyt", + "components.locked_features.locked_guests_popup.or": "Tai", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Yrityksesi tilauksessa on ongelma. Ole hyvä ja katso omaasi", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Yrityksesi tilauksessa on ongelma. Ota yhteyttä yrityksen omistajaan tai ylläpitäjään!", + "components.on_boarding.company_billing_banner.link": "yrityksen tilaussuunnitelma", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Klikkaa tästä", + "components.locked_features.locked_only_office_popup.title": "Et voi muokata tätä tiedostoa", + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "Materiaalit", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Viestien numero", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "Twaken ilmaisessa versiossa et voi käyttää enempää kuin {{$1}} uudempia viestejä.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Näytä lisää suunnitelmia", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Hakemuksesi on julkaistu, et voi muokata sitä.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Käytä * kehitysvaiheessa salliaksesi kaikki IP-osoitteet.", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "Minun hämmästyttävä sovellus", + "scenes.app.popup.appsparameters.pages.api_data_description": "Hyödyllistä tietoa Twake API:lle.", + "scenes.app.popup.appsparameters.pages.company_label": "Yrityksen omistaja", + "scenes.app.popup.appsparameters.pages.configuration_label": "Kokoonpano", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Yrityksen kehittämät sovellukset", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Voit määrittää, missä sovelluksesi näkyy.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Näyttöasetukset", + "scenes.app.popup.appsparameters.pages.error_check_needed": "Tapahtui virhe; tarkista tietosi.", + "scenes.app.popup.appsparameters.pages.error_message": "Tämä nimi on jo toisen sovelluksen käytössä; ole hyvä ja valitse toinen.", + "scenes.app.popup.appsparameters.pages.error_user_code": "virhe", + "scenes.app.popup.appsparameters.pages.event_subtitle": "Tapahtumat", + "scenes.app.popup.appsparameters.pages.filter_information": "Tämä suodatin rajoittaa API-avaimesi käytön vain liittimessäsi oleviin palvelimiin.", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Tämä nimi on jo toisen sovelluksen käytössä. Valitse toinen.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Yksinkertaistettu nimi", + "scenes.app.popup.appsparameters.pages.optimal_format": "Optimaalinen muoto: 48x48px.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "Julkaisematon sovellus toimii vain yrityksessäsi. Jos haluat asettaa sen kaikkien Twaken käyttäjien saataville, aktivoi tämä vaihtoehto.", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "Tapahtuman vastaanoton URL-osoite", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "Odotetaan...", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Kirjoitusoikeudet", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Et voi poistaa tätä sovellusta, jos se on julkaistu.", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Sovelluksesi yksinkertaistettu nimi on jo toisen sovelluksen käytössä. Vaihda se.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Sovellusta päivitettäessä tapahtui virhe.", + "scenes.app.mainview.quick_search_placeholder": "Pikahaku", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Sinun on oltava yksin työtilassa, jotta voit poistaa sen. Poista yhteiskäyttäjät ja yritä uudelleen.", + "scenes.app.popup.workspaceparameter.pages.enter": "Tulla sisään ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Käytä sovelluksiasi ja liittimiäsi", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Työtilan moderaattori", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Et voi poistua työtilasta, koska olet viimeinen järjestelmänvalvoja. Voit määrittää uuden järjestelmänvalvojan tai poistaa/arkistoida tämän työtilan.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Kaikki sovellukset", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Yrityksesi sovellukset", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Integraatiot", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Hae sovelluksia", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Tämän työtilan sovellukset", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Yrityksen kehittämät sovellukset", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Yrityksen identiteetti", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "kokoonpano", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Määritä", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Yrityksen kehittämät sovellukset", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Näyttöasetukset", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Asenna sovellus tähän työtilaan.", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Tähän työtilaan asennetut sovellukset {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Yrityksen muille alueille asennetut sovellukset {{$1}}", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Seuraavia käyttäjiä kutsuttaessa tapahtui virhe: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Tarkista, että käyttämäsi käyttäjätunnus tai sähköpostiosoite on oikea.", + "scenes.app.popup.workspaceparameter.pages.name_description": "Muuta tämän työtilan nimeä", + "scenes.app.popup.workspaceparameter.pages.no_access": "Ei pääsyä.", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Lukuoikeus", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Poista koko yrityksestä", + "scenes.app.popup.workspaceparameter.pages.research_by": "Hae sovelluksia nimen ja luokkien mukaan", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Hae sovelluksia...", + "scenes.apps.calendar.day_option": "Päivä", + "scenes.apps.messages.input.edited": "Muokattu", + "services.apps.calendar.deadline_icon": "Takaraja", + "services.apps.calendar.event_icon": "Tapahtuma", + "services.apps.calendar.move_icon": "Liikkua", + "scenes.apps.account.account.send_info": "Lähetä nämä tunnistetiedot käyttäjällesi.", + "scenes.apps.account.message_temporary": "Väliaikainen tili toimii kuten tavallinen Twake-tili, mutta sinä luot salasanan ja voit nollata sen tarvittaessa.", + "scenes.apps.account.message_user_signin": "Käyttäjäsi voi kirjautua sisään milloin tahansa tällä samalla sähköpostilla ja vaihtaa väliaikaisen tilin tavalliseksi tiliksi.", + "scenes.app.mainview.create_account": "Luo työtilasi ilmaiseksi osoitteessa ", + "scenes.apps.calendar.modals.reminder_add": "Lisää muistutus", + "scenes.apps.tasks.no_connector": "Ei liitintä", + "components.attachmentpicker.add_attachment": "Lisää liitteitä", + "components.input.copied": "Kopioitu", + "components.drive.navigators.directory_not_found": "Hakemistoa ei löydy.", + "components.drive.right_preview.suppress_link": "Sulje linkki", + "components.drive.right_preview.create_link": "Luo pääsylinkki", + "scenes.apps.board.active_tasks": "Aktiiviset tehtävät", + "scenes.apps.board.display_as": "Näytä muodossa", + "scenes.apps.drive.used": "käytetään tässä kansiossa", + "scenes.apps.calendar.reminders": "muistutus", + "components.tagpicker.notag": "Ei tagia", + "components.calendar.calendarselector.from": "From", + "scenes.apps.drive.move_text2": "Liikkua", + "components.attachmentpicker.from_computer": "laitteestasi", + "components.attachmentpicker.from_twake": "Twake Documentsista", + "components.attachmentpicker.file": "Tiedosto", + "components.attachmentpicker.remove_attach": "Poista liite", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Nykyinen käyttäjätunnus", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Nykyinen työtilan tunnus", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Nykyisen ryhmän tunnus", + "scenes.app.mainview.channel_description": "Kuvaile kanavaa", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Kutsu kaikki työtilan käyttäjät automaattisesti tälle kanavalle", + "scenes.client.channelbar.channelmemberslist.title": "Käyttäjät kohteessa {{$1}}", + "components.notifications.hidden_notifications_button.children": "Uusia viestejä", + "scenes.client.channelbar.channelmemberslist.no_members": "Tällä kanavalla ei ole käyttäjiä, voit kutsua heidät napsauttamalla Lisää käyttäjiä.", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} lisäsi uuden {{$2}}-välilehden {{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} poisti välilehden {{$2}} {{$3}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} lisäsi uuden liittimen {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} poisti liittimen {{$2}}", + "scenes.client.channelbar.channelmemberslist.tag": "Sinä", + "general.verify": "Vahvista", + "components.unverified_account.typography_text_danger": "Sinulla on {{$1}} päivää jäljellä kokeilujaksoa. Kokeilutili estetään 7 päivän kuluttua ja poistetaan pysyvästi 1 kuukauden rekisteröinnin jälkeen. Voit vahvistaa tilisi napsauttamalla \"Vahvista tilini\" -painiketta sinulle lähettämässämme vahvistussähköpostissa.", + "components.unverified_account.verification_details": "Olemme lähettäneet vahvistustiedot osoitteeseen", + "components.blocked_account.trial_period_over": "Kokeilujaksosi on ohi. Avaa tilisi lukitus ja pääset käyttämään kaikkia toimintoja vahvistamalla tilisi sähköpostivahvistuksella", + "components.add_mails_workspace.text_area_placeholder": "Anna käyttäjiesi sähköpostiosoitteet*", + "components.verify_mail.title_1": "Onnittelut", + "components.verify_mail.title_2": "Olet nyt virallinen Twaken käyttäjä!", + "components.verify_mail.button": "Lisää käyttäjä", + "components.verify_mail.text": "Ensinnäkin sinun on vahvistettava sähköpostiosoitteesi. Olemme lähettäneet vahvistuslinkin osoitteeseen", + "components.verify_mail.paragraph": "Voit tehdä sen myöhemmin, jos haluat, mutta vahvistamattomilla tileillä on pääsy vain rajoitettuun Twaken versioon", + "services.console_services.toaster.add_emails_error": "Virhe lisättäessä sähköposteja", + "services.console_services.toaster.add_email_error_message": "Virhe lisättäessä {{$1}}", + "services.console_services.toaster.success_verify_email": "Vahvistuslinkki on lähetetty sähköpostitilillesi", + "scenes.app.popup.workspaceparameter.edit_from_console": "Katso konsolista", + "services.console_services.toaster.success_invite_emails": "{{$1}} käyttäjän lisäys onnistui", + "scenes.client.channels_bar.modals.guest_management.title": "Hallinnoi vieraita kohteessa {{$1}}", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Hae vieraita tai odottavia sähköposteja", + "scenes.client.channels_bar.modals.guest_management.tips": "Aloita sähköpostin lisääminen tai etsiminen käyttämällä yllä olevaa syötettä", + "components.richtexteditor.toolbar.bold": "Lihavoitu", + "components.richtexteditor.toolbar.underline": "Korostaa", + "components.richtexteditor.toolbar.italic": "Kursiivi", + "components.richtexteditor.toolbar.strikethrough": "Yliviivattu", + "components.richtexteditor.toolbar.code": "Koodi", + "components.richtexteditor.toolbar.unordered-list": "Ranskalaiset viivat", + "components.richtexteditor.toolbar.ordered-list": "Tilattu lista", + "components.richtexteditor.toolbar.blockquote": "Lohkolainaus", + "components.richtexteditor.toolbar.code-block": "Koodilohko", + "components.locked_features.locked_history_banner.title": "Olet juuri saavuttanut viestirajan", + "components.locked_features.locked_history_banner.description": "Yritykselläsi on paljon viestejä! Päivitä nyt, niin pääset käyttämään kaikkea viestihistoriaasi.", + "components.locked_features.locked_history_banner.button": "Lue lisää", + "components.locked_features.locked_guests_popup.title": "Vieraat-ominaisuus on lukittu", + "components.locked_features.locked_guests_popup.subtitle": "Tämä ominaisuus ei ole käytettävissä Twaken ilmaisessa versiossa", + "components.locked_features.locked_guests_popup.description": "Oho!! Vaikuttaa siltä, että haluat kutsua ulkoisia käyttäjiä työtilaan. Sinun kannattaa harkita suunnitelmasi päivittämistä, jos haluat tehdä yhteistyötä vieraiden ja ulkoisten kumppaneiden kanssa. Tutustu hinnoitteluvaihtoehtoihimme ja valitse tiimisi yhteistyötarpeisiisi paras vaihtoehto.", + "components.locked_features.locked_guests_popup.learn_more_button": "Lue lisää", + "components.on_boarding.popups.blocked_company.title": "Yrityksesi on lukittu maksuongelman vuoksi", + "components.on_boarding.popups.blocked_company.description": "Twake-tilauksesi on vanhentunut. Ota yhteyttä yrityksesi omistajaan tai järjestelmänvalvojaan uusitaksesi sen ja pystyt kommunikoimaan tiimisi kanssa uudelleen!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Haluatko tietää lisää yritysten tilaussuunnitelmasta?", + "components.on_boarding.popups.blocked_company.or": "Tai", + "components.on_boarding.popups.blocked_company.company_selector": "Vaihda toiseen yritykseen", + "scenes.apps.tasks.select_user_button": "Tarkastele toisen käyttäjän tehtäviä", + "scenes.apps.tasks.select_user": "Etsi käyttäjä", + "scenes.apps.messages.input.attach_file.from_computer": "Tietokoneelta", + "scenes.app.popup.workspaceparameter.pages.table_title": "Nimi", + "scenes.client.main_view.main_header.search_input": "Hae", + "scenes.apps.drive.new_link_title": "Uusi linkki", + "scenes.apps.drive.default_link_name": "Nimetön", + "components.emoji_picker.input_search_placeholder": "Hae", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Et voi lisätä viestiin enempää kuin {{$2}} tiedostoa", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Poistit tämän viestin", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} poisti viestinsä", + "components.member.user_parts.and_more_user_text": " ja {{$1}} enemmän käyttäjiä", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Luo yksityinen kanava", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " sen sijaan", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Et voi lisätä enempää kuin 10 käyttäjää", + "general.uploading": "Lähetetään", + "components.upload.drop_files.toaster.error": "Et voi lähettää enempää kuin {{$1}} tiedostoa", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Rooli", + "general.email": "Sähköposti", + "components.locked_features.locked_workspace_popup.title": "Et voi luoda lisää työtiloja", + "components.locked_features.locked_workspace_popup.subtitle": "Ilmaisessa versiossa sinulla voi olla vain yksi työtila yrityksessäsi.", + "components.locked_features.locked_workspace_popup.text": "Oho!! Haluatko luoda uuden työtilan yritykseesi? Sinun kannattaa harkita suunnitelmasi päivittämistä. Tutustu hinnoitteluvaihtoehtoihimme ja valitse paras vaihtoehto tiimin yhteistyötarpeisiisi.", + "components.locked_features.locked_only_office_popup.subtitle": "Ilmaisessa versiossa et voi käyttää onlyofficea.", + "components.locked_features.locked_only_office_popup.text": "Oho!! Vaikuttaa siltä, että haluat muokata Twaken tiedostoa. Sinun kannattaa harkita suunnitelmasi päivittämistä, jos haluat tehdä yhteistyötä Office-tiedostojen parissa. Tutustu hinnoitteluvaihtoehtoihimme ja valitse tiimisi yhteistyötarpeisiisi paras vaihtoehto.", + "components.locked_features.locked_drive_popup.title": "Olet juuri saavuttanut ajorajan", + "components.locked_features.locked_drive_popup.subtitle": "Ilmaisessa versiossa voit tallentaa vain 6 Gt.", + "general.resume": "Jatkaa", + "general.pause": "Tauko", + "'": "'", + "\"": "\"", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Oletustyötila", + "login.create_account": "Luo tili", + "login.login_error": "Virhe kirjautumisen aikana", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Kukaan ei ole vielä kutsunut sinua työtilaan.", + "scenes.apps.messages.message.types.no_message_in_thread": "Kukaan ei vastannut vielä.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Kutsu kaikki työtilan käyttäjät automaattisesti tälle kanavalle", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Olet poistamassa {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Sinulla on edelleen {{$1}} jäseniä ryhmässä {{$2}}. Sinun tulee poistaa kaikki jäsenet, jotta voit poistaa tämän työtilan.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Ymmärrän, että kaikki työtilani viestit ja tiedostot poistetaan.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Logon maksimikoko on 5 mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Väärä muoto, vain png gif ja jpg ovat sallittuja", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Tuntematon virhe", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Virhe", + "scenes.app.channelsbar.currentuser.reset": "Nollaa", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Kirjoita vähintään kolme kirjainta näyttäville käyttäjille", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Käyttäjiä ei löytynyt", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Emojia ei löytynyt", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Komentoa ei löytynyt", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} kirjoittaa...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} ja {{$2}} kirjoittavat...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} ja {{$3}} lisää käyttäjiä kirjoittaa...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Yrityksesi on saavuttanut {{$1}} jäsenten enimmäisrajan. Ole kiltti ", + "components.locked_features_components.locked_invite_alert.message_link": "päivittää yritystäsi", + "components.locked_features_components.locked_invite_alert.message_part_2": " kutsua lisää jäseniä.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " ota yhteyttä yrityksesi omistajaan tai ylläpitäjään.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Katso kaikki yritykseni jäsenet konsolissa", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Jos et tiedä kuinka täyttää nämä, mene osoitteeseen ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Yksityinen avain", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Sovelluksen {{$1}} poistaminen onnistui!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Virhe poistettaessa sovellusta {{$1}} !", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Kuvaile hakemustasi muutamalla sanalla", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Uusi integraatio", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Ymmärrän, että tämän yrityksen omistaja ja järjestelmänvalvojat voivat muokata ja julkaista tätä sovellusta.", + "twake.application.access.title": "Valitse sovelluksellesi oikeat laajuudet.", + "twake.application.access.no_default_scopes_available'": "Tällä integraatiolla ei ole {{$1}}-käyttöoikeutta", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake API -dokumentaatio", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "{{$1}} -sovellus onnistui!", + "scenes.app.integrations_parameters.add_application": "Uusi integraatio", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Kehittäjäasetukset", + "components.rich_text_editor.plugins.suggestions.loading": "Etsitkö lisää", + "components.open_desktop_popup.subtitle": "avattu Twake-sovelluksessa", + "components.open_desktop_popup.open_here_link": "Avaa sen sijaan tästä", + "molecules.download_banner.title": "Ota kaikki irti Twakesta ja lataa työpöytäsovellus nyt", + "molecules.download_banner.download_button": "Lataa työpöytäsovellus", + "scenes.app.channelsbar.channel_copy_link": "Kopioi kanavan linkki", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Päivitetty onnistuneesti", + "components.searchpopup.no_results_for": "Ei ollut tuloksia kohteelle", + "components.searchpopup.try_new_search": "Kokeile uutta hakua", + "components.searchpopup.all": "Kaikki", + "components.searchpopup.chats": "Chatit", + "components.searchpopup.media": "Media", + "components.searchpopup.files": "Tiedostot", + "components.searchpopup.recent_chats": "Viimeaikaiset keskustelut", + "components.searchpopup.recent_media": "Viimeaikainen media", + "components.searchpopup.recent_files": "Viimeaikaiset tiedostot", + "components.searchpopup.recent_channels_and_contacts": "Viimeisimmät kanavat ja yhteystiedot", + "components.searchpopup.header_title": "Hae", + "components.searchpopup.scope.company": "kaikessa seurassa", + "components.searchpopup.scope.channel": "tällä kanavalla", + "components.searchpopup.channels": "Kanavat", + "components.searchpopup.messages": "Viestit" +} diff --git a/twake/frontend/public/locales/fr.json b/twake/frontend/public/locales/fr.json index 73009b0d71..2dcb5e7c88 100644 --- a/twake/frontend/public/locales/fr.json +++ b/twake/frontend/public/locales/fr.json @@ -18,6 +18,8 @@ "general.update": "Mettre à jour", "general.remove": "Supprimer", "general.add": "Ajouter", + "general.yes": "Oui", + "general.no": "Non", "general.connexion_status.disconnected": "Vous êtes hors ligne", "general.connexion_status.connected": "Vous êtes connecté", "general.connexion_status.connecting": "Reconnexion en cours…", @@ -103,7 +105,7 @@ "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}} seulement", "scenes.apps.messages.left_bar.stream.notifications.never": "Aucun message", "scenes.apps.parameters.workspace_sections.workspace": "Espace de travail", - "scenes.apps.parameters.workspace_sections.members": "Participants", + "scenes.apps.parameters.workspace_sections.members": "Participants de la chaîne", "scenes.apps.parameters.group_sections.workspaces": "Espaces de travail", "scenes.apps.parameters.group_sections.apps": "Applications", "scenes.apps.account.title": "Paramètres du compte", @@ -280,7 +282,7 @@ "scenes.app.channelsbar.currentuser.reactivate_notifications": "Réactiver", "scenes.app.channelsbar.currentuser.user_parameter": "Paramètres de notification", "scenes.app.channelsbar.channelsuser.new_private_discussion": "Nouvelle discussion privée", - "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Aucun message privé, invitez des utilisateurs !", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Aucun message privé, invitez des utilisateurs !", "scenes.app.channelsbar.channelsuser.private_messages": "Messages directs", "scenes.app.channelsbar.channelsworkspace.channel_title": "CHAÎNES", "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "FAVORIS", @@ -290,6 +292,7 @@ "scenes.app.channelsbar.guest_management": "Gestion des invités", "scenes.app.channelsbar.read_sign": "Marquer comme lu", "scenes.app.channelsbar.unread_sign": "Marquer comme non lu", + "scenes.app.channelsbar.channel_copy_link": "Copier le lien de la chaîne", "scenes.app.channelsbar.channel_leaving": "Quitter la chaîne", "scenes.app.channelsbar.channel_removing": "Supprimer la chaîne", "scenes.app.channelsbar.company_invitation_alert_subtitle": "Vous pouvez importer ces chaînes dans votre entreprise pour rester organisé en cliquant sur ce cadre.", @@ -383,13 +386,19 @@ "scenes.app.popup.createworkspacepage.add_subtitle": "Besoin de plus de place ?", "scenes.app.popup.createworkspacepage.create_new_workspace": "Créer un nouvel espace de travail", "scenes.app.popup.createworkspacepage.placeholder_name": "Nom de l'espace de travail", - "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Configurez la fréquence des notifications mobile.", + "scenes.app.popup.userparameter.pages.email_notif_delay_never": "Jamais", + "scenes.app.popup.userparameter.pages.email_notif_delay_quarter_hour": "15 minutes", + "scenes.app.popup.userparameter.pages.email_notif_delay_one_day": "1 jour", + "scenes.app.popup.userparameter.pages.email_notif_delay_one_hour": "1 heure", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Configurez les notifications push mobiles.", "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Fréquence des notifications", "scenes.app.popup.userparameter.pages.keywords_notif_description": "Mettre en surbrillance les mots clés suivants :", - "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Configurez la fréquence des notifications mail.", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Configurer l'envoi des notifications manquées par email", "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Choisissez une période pendant laquelle vous ne recevez pas de notifications.", "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Ne pas déranger la nuit", "scenes.app.popup.userparameter.pages.notif_content_label": "Contenu des notifications", + "scenes.app.popup.userparameter.pages.notification_sound.defaut": "Par défaut", + "scenes.app.popup.userparameter.pages.notification_sound.none": "Désactivé", "scenes.app.mainview.quick_search_placeholder": "Recherche rapide", "scenes.app.popup.userparameter.personnal_workspaces_title": "Vos espaces de travail", "scenes.app.popup.userparameter.pages.private_message_content.show": "Afficher le contenu des messages privés", @@ -417,7 +426,7 @@ "scenes.app.popup.workspaceparameter.pages.company_name_description": "Modifiez le nom de cette entreprise", "scenes.app.popup.workspaceparameter.pages.company_name_label": "Nom de l'entreprise", "scenes.app.popup.workspaceparameter.pages.configuration_notif": "configuration", - "scenes.app.popup.workspaceparameter.pages.configure_button": "Configurer", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Préférences ", "scenes.app.popup.workspaceparameter.pages.description": "Description", "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Applications développées par votre entreprise", "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Préférences d'affichage", @@ -532,10 +541,11 @@ "scenes.apps.messages.message.reply_button": "Répondre", "scenes.apps.messages.message.save_button": "Enregistrer", "scenes.apps.messages.message.show_button": "Afficher", - "scenes.apps.messages.message.show_responses_button": "Afficher toutes les réponses", + "scenes.apps.messages.message.show_responses_button": "Voir les réponses précédentes", "scenes.apps.messages.message.types.first_channel_message_text": "Ceci est le premier message de la chaîne", "scenes.apps.messages.message.types.first_message_text": "C'est le premier message", "scenes.apps.messages.message.types.no_message_in_thread": "Personne n'a répondu.", + "scenes.apps.messages.message.user_deactivated": "Vous consultez les archives d'un compte désactivé", "scenes.apps.messages.messageslist.get_writing_user": "est en train d'écrire...", "scenes.apps.messages.messageslist.get_writing_users": "sont en train d'écrire...", "scenes.apps.messages.messageslist.go_last_message_button": "Aller au dernier message", @@ -743,6 +753,8 @@ "general.user.role.company.member": "Utilisateur", "general.user.role.company.guest": "Invité", "general.user.deleted": "Compte supprimé", + "general.user.deactivated": "Cet utilisateur n'est plus dans cette l'entreprise", + "general.user.connected": "Connecté", "components.richtexteditor.toolbar.bold": "Gras", "components.richtexteditor.toolbar.underline": "Souligné", "components.richtexteditor.toolbar.italic": "Italique", @@ -823,7 +835,7 @@ "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Site web", "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Date de création", "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Version", - "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Afficher", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Afficher détails", "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Retirer de l'entreprise", "scenes.app.integrations_parameters.company_applications_table.name": "Nom", "scenes.app.integrations_parameters.company_applications_table.title": "Installé dans votre entreprise", @@ -847,5 +859,63 @@ "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Mauvais format, seuls les png, gif et jpg sont autorisés", "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Erreur inconnue", "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Erreur", - "scenes.app.channelsbar.currentuser.reset": "Réinitialiser" + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Mise à jour réussie", + "scenes.app.channelsbar.currentuser.reset": "Réinitialiser", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Écrivez au moins trois lettres pour afficher des utilisateurs", + "components.rich_text_editor.plugins.suggestions.loading": "Recherche en cours", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Aucun utilisateur trouvé", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Aucun emoji trouvé", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Aucune commande trouvé", + "scenes.join.loading": "Chargement…", + "scenes.join.wrong_link_title": "Ce lien n'est plus disponible", + "scenes.join.twake_description": "Twake est un espace de travail numérique à code ouvert conçu pour améliorer la productivité de votre équipe", + "scenes.join.login_first_button": "Connectez-vous ou créez d'abord un compte", + "scenes.join.wrong_link_description": "Demandez à la personne qui vous a invité(e) de rejoindre cette entreprise par un nouveau lien ou créez votre propre entreprise", + "scenes.join.join_the_team_button": "Rejoindre l'équipe", + "scenes.join.create_the_company_button": "Créer l'entreprise", + "scenes.join.join_workspace_from_company": "Rejoignez {{$1}} à partir de {{$2}} !", + "\"": "\"", + "'": "'", + "login.create_account": "Créer un compte", + "login.login_error": "Erreur lors de la connexion", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} est en train d'écrire...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} et {{$2}} sont en train d'écrire...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} et {{$3}} autres utilisateurs sont en train d'écrire...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Votre entreprise a atteint sa limite maximale de {{$1}} membres. Veuillez ", + "components.locked_features_components.locked_invite_alert.message_link": "mettre à niveau votre entreprise", + "components.locked_features_components.locked_invite_alert.message_part_2": " pour inviter davantage de membres.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " contacter le propriétaire ou l'administrateur de votre entreprise.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Voir tous les membres de mon entreprise sur la console", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Décrivez votre application en quelques mots", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Nouvelle intégration", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Je comprends que le propriétaire et les administrateurs de cette entreprise pourront modifier et publier cette application.", + "twake.application.access.title": "Sélectionnez les portées adaptées à votre application.", + "twake.application.access.no_default_scopes_available'": "Cette intégration n'a pas d'accès {{$1}}.", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "la documentation de l'API Twake.", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Si vous ne savez pas comment les remplir, consultez ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Clé privée", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "L'application {{$1}} a été supprimée avec succès !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Erreur lors de la suppression de l'application {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Application {{$1}} réussie !", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Paramètres du développeur", + "scenes.app.integrations_parameters.add_application": "Nouvelle intégration", + "components.open_desktop_popup.subtitle": "Ouvert dans l'application Twake", + "components.open_desktop_popup.open_here_link": "Ouvrir dans la version web", + "molecules.download_banner.title": "Tirez le meilleur parti de Twake, téléchargez l'application de bureau maintenant", + "molecules.download_banner.download_button": "Télécharger l'application de bureau", + "components.searchpopup.no_results_for": "Il n'y a pas eu de résultats pour", + "components.searchpopup.try_new_search": "Essayez une nouvelle recherche", + "components.searchpopup.all": "Tout", + "components.searchpopup.chats": "Chats", + "components.searchpopup.media": "Médias", + "components.searchpopup.files": "Des dossiers", + "components.searchpopup.recent_chats": "Chats récents", + "components.searchpopup.recent_media": "Médias récents", + "components.searchpopup.recent_files": "Fichiers récents", + "components.searchpopup.recent_channels_and_contacts": "Canaux et contacts récents", + "components.searchpopup.header_title": "Chercher", + "components.searchpopup.scope.company": "dans toute compagnie", + "components.searchpopup.scope.channel": "dans ce canal", + "components.searchpopup.channels": "Canaux", + "components.searchpopup.messages": "messages" } diff --git a/twake/frontend/public/locales/it.json b/twake/frontend/public/locales/it.json new file mode 100644 index 0000000000..e997cf7c5b --- /dev/null +++ b/twake/frontend/public/locales/it.json @@ -0,0 +1,910 @@ +{ + "general.save": "Salva", + "scenes.login.create_account.email_used": "Questa posta elettronica è già in uso.", + "scenes.login.create_account.username": "Nome utente", + "scenes.login.create_account.username_already_exist": "Questo nome utente è già in uso", + "scenes.login.create_account.fill_in_username": "Devi inserire il tuo nome utente", + "scenes.login.forgot_password.invalid_code": "Questo codice non è valido.", + "scenes.login.forgot_password.text3": "Inserisci una nuova password per il tuo account.", + "scenes.login.forgot_password.password": "Password", + "scenes.login.forgot_password.password2": "Conferma password", + "scenes.login.forgot_password.password_dont_match": "Le tue password non corrispondono o sono troppo corte. Si prega di digitare una password con almeno 8 caratteri.", + "scenes.login.home.title": "Accedi a Twake", + "scenes.login.create_account.step_1_subtitle": "Non potrebbe essere più semplice: abbiamo solo bisogno di alcune informazioni.", + "scenes.login.create_account.step_2_subtitle_a": "Aggiungi il tuo nome completo per consentire agli altri utenti di riconoscerti.", + "scenes.app.workspaces.welcome_page.twake_team": "Twake", + "scenes.app.workspaces.welcome_page.welcome_header": "Benvenuto a Twake!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Puoi collegare più indirizzi e-mail al tuo account; verrà utilizzato un solo indirizzo per inviarti le notifiche.", + "scenes.app.workspaces.welcome_page.main_mail_title": "Indirizzo principale", + "scenes.app.workspaces.welcome_page.other_mail_title": "Indirizzi secondari", + "general.open": "Aprire", + "scenes.app.channelsbar.read_sign": "Segna come letto", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Nuovo link generato", + "scenes.app.popup.appsparameters.pages.alert_published_app": "La tua domanda è pubblicata, non puoi modificarla.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Utilizzare * in fase di sviluppo per consentire tutti gli indirizzi IP.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Privilegi dell'applicazione", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "La pubblicazione della tua domanda è attualmente in attesa di convalida da parte del team Twake.", + "scenes.app.popup.appsparameters.pages.button_force": "Forza in tutta l'azienda", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "Evento di tipo '{{$1}}' e id '{{$2}}' con passivi '{{$3}}'", + "scenes.app.popup.appsparameters.pages.company_label": "Proprietario della compagnia", + "scenes.app.popup.appsparameters.pages.configuration_label": "Configurazione", + "scenes.app.popup.appsparameters.pages.go_back": "Indietro", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Questo nome è già utilizzato da un'altra applicazione. Si prega di sceglierne un altro.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Nome semplificato", + "scenes.app.popup.appsparameters.pages.installation": "Installare.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Inizia scrivendo il tuo messaggio in formato JSON.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Applicazione interna", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Vai alla documentazione per generare la tua configurazione in formato JSON.", + "scenes.app.popup.appsparameters.pages.loading": "Caricamento in corso...", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Dati passivi che verranno inviati al prossimo Evento", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Modifica i dati pubblici della tua applicazione.", + "scenes.app.popup.appsparameters.pages.optimal_format": "Formato ottimale: 48x48px.", + "scenes.app.popup.appsparameters.pages.public_availability_application": "Applicazione pubblica", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Devi essere il solo partecipante nello spazio di lavoro per rimuoverlo. Rimuovi i tuoi collaboratori e riprova.", + "scenes.app.popup.workspaceparameter.pages.enter": "Entrare ", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Moderatore dello spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Non puoi lasciare lo spazio di lavoro, perché sei l'ultimo amministratore. Puoi definire un nuovo amministratore o cancellare/archiviare questo spazio di lavoro.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Tutte le applicazioni", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Le applicazioni della tua azienda", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Installa l'applicazione in questo spazio di lavoro.", + "scenes.app.popup.workspaceparameter.pages.name_label": "Nome dello spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Accesso di scrittura", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Le tue applicazioni", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Pagamenti e abbonamenti", + "scenes.app.workspacesbar.components.change_company_title": "Cambia azienda", + "scenes.apps.calendar.day_option": "Giorno", + "scenes.apps.calendar.modals.description_placeholder": "Descrizione", + "scenes.apps.calendar.modals.details_title": "Particolari", + "scenes.apps.calendar.modals.event_adresse_placeholder": "Indirizzo", + "scenes.apps.calendar.modals.event_description_placeholder": "Descrizione", + "components.searchpopup.loading": "Caricamento di più risultati", + "components.searchpopup.filter_ws": "Filtra le aree di lavoro", + "components.searchpopup.tags": "tag", + "components.searchpopup.size": "Misurare", + "components.searchpopup.creation": "Creazione", + "components.searchpopup.update_search": "Aggiorna ricerca", + "components.searchpopup.last_modif": "Ultima modifica", + "components.searchpopup.sender": "Mittente", + "components.searchpopup.mentions": "menzioni", + "components.searchpopup.only_pinned": "Solo messaggi appuntati", + "components.alert.confirm": "Conferma la tua azione", + "components.alert.confirm_click": "Conferma la tua azione facendo clic su OK.", + "components.searchpopup.tasks": "Compiti", + "scenes.app.mainview.advanced_search_placeholder": "Ricerca Avanzata", + "scenes.apps.drive.right_preview.public": "Accesso pubblico", + "components.drive.elements.configurate_mod": "Configura la modalità...", + "components.drive.elements.manage_version": "Gestisci versioni", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Cerca canale, utente o messaggi diretti", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Crea una nuova scheda", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "Rinomina {{$1}}", + "components.connectorslistmanager.add_connectors": "Aggiungi connettori", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "Applicazione", + "scenes.client.channelbar.channelmemberslist.no_members": "Non ci sono utenti in questo canale, puoi invitarli facendo clic su Aggiungi utenti.", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Nascondi discussione", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} email verranno aggiunte", + "components.newversion.new_version_component.row.part_2": "ti consigliamo di ricaricare l'app e goderti le nostre nuove funzionalità!", + "components.newversion.new_version_component.link": "Clicca qui per ricaricare", + "components.newversion.new_version_modal.title": "Nuovo aggiornamento disponibile !", + "scenes.apps.drive.download_all_button": "Scarica tutto", + "components.inputs.input_with_select.input.placeholder": "Nome del canale", + "components.inputs.input_with_select.select.placeholder": "Nome della sezione", + "components.inputs.input_with_select.select.no_sections": "Puoi raggruppare i tuoi canali qui", + "components.inputs.input_with_select.button.tooltip": "Imposta una sezione del canale", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} ha aggiunto {{$2}} al canale", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} ha rimosso {{$2}} dal canale", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} ha cambiato la descrizione", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} ha rinominato il canale in {{$2}}", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} ha aggiunto una nuova scheda {{$2}} {{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} rimosso scheda {{$2}} {{$3}}", + "scenes.client.channelbar.channelmemberslist.tag": "Voi", + "general.re_send": "Invia di nuovo", + "components.unverified_account.verification_details": "Abbiamo inviato un'e-mail di verifica a", + "components.account_verification_status_sentence": "Lo stato del tuo account è: {{$1}}", + "components.account_verication_status_unverified": "Non verificato", + "components.account_verication_status_blocked": "bloccato", + "components.unverified_account.re_send_email": "Non hai ricevuto l'e-mail?", + "components.verify_mail.title_1": "Congratulazioni", + "components.richtexteditor.toolbar.code": "Codice", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Clicca qui", + "components.on_boarding.popups.blocked_company.or": "o", + "components.on_boarding.popups.blocked_company.company_selector": "Passa a un'altra azienda", + "scenes.apps.tasks.select_user": "Cerca utente", + "components.locked_features.locked_only_office_popup.text": "Ops!! Sembra che tu voglia modificare il file da Twake. Potresti prendere in considerazione l'aggiornamento del tuo piano se desideri collaborare sui file dell'ufficio. Esplora le nostre opzioni di prezzo e seleziona l'opzione migliore per le esigenze di collaborazione del tuo team.", + "components.locked_features.locked_drive_popup.title": "Hai appena raggiunto il limite di unità", + "components.locked_features.locked_drive_popup.subtitle": "Nella versione gratuita, puoi archiviare solo 6 GB.", + "general.resume": "Riprendere", + "general.pause": "Pausa", + "scenes.app.integrations_parameters.title": "integrazioni", + "scenes.app.integrations_parameters.applications_table.name": "Nome", + "scenes.app.integrations_parameters.applications_table.title": "Altre integrazioni", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Cerca applicazione", + "scenes.join.wrong_link_title": "Questo link non è più disponibile", + "scenes.join.wrong_link_description": "Chiedi alla persona che ti ha invitato a entrare a far parte di questa azienda un nuovo collegamento o crea la tua azienda", + "scenes.join.create_the_company_button": "Crea l'azienda", + "scenes.join.join_workspace_from_company": "Unisciti a {{$1}} da {{$2}}!", + "scenes.join.twake_description": "Twake è uno spazio di lavoro digitale open source creato per migliorare la produttività del tuo team", + "scenes.join.login_first_button": "Accedi o crea un account prima", + "scenes.join.join_the_team_button": "Unisciti alla squadra", + "general.close": "Vicino", + "general.cancel": "Annulla", + "general.retry": "Riprova", + "general.create": "Crea", + "general.edit": "Modifica", + "general.continue": "Continua", + "general.back": "Indietro", + "general.confirm": "Conferma", + "general.delete": "Eliminare", + "general.archive": "Archivio", + "general.unarchive": "Annulla archiviazione", + "general.help": "Aiuto", + "general.help.support": "Supporto", + "general.help.documentation": "Documentazione", + "general.send": "Invia messaggio", + "general.update": "Aggiorna", + "general.remove": "Rimuovi", + "general.add": "Aggiungi", + "general.connexion_status.disconnected": "Sei offline", + "general.connexion_status.connected": "Sei online", + "general.connexion_status.connecting": "Riconnessione in corso…", + "application.load.longer": "Il server impiega più tempo del previsto per rispondere, attendere o ricaricare la pagina...", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Thread dei messaggi", + "scenes.app.workspaces.create_company.group_data": "Configura il tuo nuovo gruppo", + "scenes.app.workspaces.create_company.group_data.group_type": "Tipo di gruppo", + "scenes.app.workspaces.create_company.group_data.group_type.company": "Azienda o dipartimento aziendale", + "scenes.app.workspaces.create_company.group_data.group_type.public_organization": "Organizzazione pubblica", + "scenes.app.workspaces.create_company.group_data.group_type.university_school": "Università o scuola", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Società, club o beneficenza", + "scenes.app.workspaces.create_company.group_data.group_type.other_group": "Altro", + "scenes.app.workspaces.create_company.group_data.group_size": "Dimensione del gruppo", + "scenes.app.workspaces.create_company.group_data.group_size.less_3": "Meno di 4 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4 - 10 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11 - 49 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50 - 99 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100 - 499 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500 - 999 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000 - 4999 utenti", + "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "Più di 5000 utenti", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "Attività principale", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Cibo", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "Banca / Assicurazione", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Stampa / Carta", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "Edilizia / Materiali da costruzione", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "Immobiliare", + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "Materiali", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "Chimica", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Vendita/Commercio/Distribuzione", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Editoria / Comunicazione / Multimedia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Elettronica/Elettricità/Energia", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Studi e consigli", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "Industria farmaceutica", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "IT / Telecomunicazioni", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Macchinari / Automotive", + "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "Servizi per gli affari", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Divertimento", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "Tessile / Abbigliamento / Scarpe", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Trasporti / Logistica", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Ricerca", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "Formazione scolastica", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Amministrazione", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "Altro", + "components.application.messages": "Messaggi", + "components.drive_dropzone.uploading": "Caricamento in corso...", + "components.user_picker.modal_no_result": "Nessun risultato trovato", + "components.users_picker.add_me": "Aggiungimi", + "scenes.app.workspaces.create_company.invitations.title": "Configura il tuo spazio di lavoro.", + "scenes.app.header.disconnected": "Sei disconnesso", + "scenes.app.header.disconnected.reload": "Ricarica", + "scenes.app.header.alt_notifications": "Notifiche", + "scenes.apps.calendar.calendar.week_btn": "Settimana", + "scenes.apps.calendar.calendar.list_btn": "Elenco", + "scenes.apps.calendar.event_edition.deadline_tag": "Scadenza", + "scenes.apps.calendar.event_edition.checkbox_all_day": "Tutto il giorno", + "scenes.apps.calendar.event_edition.title_confidentiality": "Riservatezza", + "scenes.apps.calendar.event_view.article_until": "a", + "scenes.apps.calendar.calendar_modal.participants": "partecipanti", + "scenes.apps.calendar.calendar_modal.placeholder": "Nome", + "scenes.apps.calendar.left.calendars": "Calendari", + "scenes.apps.drive.left.search": "Ricerca", + "scenes.apps.drive.navigators.navigator_content.directory_name": "Nome della directory", + "scenes.apps.drive.navigators.navigator_content.files": "File", + "scenes.apps.drive.navigators.navigator_labels.title": "Etichette", + "scenes.apps.drive.navigators.new_file.untitled": "Senza titolo", + "scenes.apps.drive.navigators.new_file.create_file.type": "Tipo", + "scenes.apps.drive.navigators.new_file": "Nuovo file", + "scenes.apps.drive.preview_bloc.operations_download": "Scarica", + "scenes.apps.drive.preview_bloc.error_file": "File non trovato", + "scenes.apps.drive.right_preview.operations_restore": "Ristabilire", + "scenes.apps.drive.right_preview.operations_delete": "Sposta nel cestino", + "scenes.apps.drive.right_preview.public_link": "Link pubblico", + "scenes.apps.messages.messages": "Messaggi", + "scenes.apps.messages.chatbox.chat.delete_message": "Elimina questo messaggio", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "Elimina il messaggio", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Nome", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Aggiungi ai preferiti", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Rimuovi dai preferiti", + "scenes.apps.messages.left_bar.stream.notifications": "Notifiche...", + "scenes.apps.messages.left_bar.stream.notifications.all": "Qualsiasi messaggio", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} e {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "Solo {{$1}}", + "scenes.apps.messages.left_bar.stream.notifications.never": "Niente", + "scenes.apps.parameters.workspace_sections.workspace": "Spazio di lavoro", + "scenes.apps.parameters.workspace_sections.members": "Partecipanti", + "scenes.apps.parameters.group_sections.workspaces": "Spazi di lavoro", + "scenes.apps.parameters.group_sections.apps": "App", + "scenes.apps.account.title": "Parametri dell'account", + "scenes.apps.account.account.menu_title": "Account", + "scenes.apps.account.languages.menu_title": "Lingua", + "scenes.apps.account.account.firstname": "Nome", + "scenes.apps.account.account.lastname": "Cognome", + "scenes.apps.account.account.username": "Nome utente", + "scenes.apps.account.account.change_username": "Cambia il tuo nome utente univoco.", + "scenes.apps.account.account.emails": "E-mail", + "scenes.apps.account.account.main_email": "E-mail principale", + "scenes.apps.account.account.email_add": "Aggiungi una nuova e-mail", + "scenes.apps.account.account.email_add_modal.invalid_code": "Questo codice non è valido", + "scenes.apps.account.account.password": "Password", + "scenes.apps.account.account.password_modal.old_password": "Password attuale", + "scenes.apps.account.account.password_modal.password": "Nuova password", + "scenes.apps.account.account.password_modal.bad_old_password": "La vecchia password non è corretta.", + "scenes.apps.account.account.password_modal.bad_password": "Le tue password non corrispondono o sono troppo corte. Si prega di digitare una password con almeno 8 caratteri.", + "scenes.apps.account.account.logout": "Disconnettersi", + "scenes.apps.account.languages.text": "Cambia la lingua di Twake.", + "scenes.apps.account.notifications.title": "Notifiche", + "scenes.apps.account.notifications.keywords_subtitle": "Parole chiave", + "scenes.apps.account.notifications.keywords_placeholder": "dev, wifi, codice, ...", + "scenes.apps.account.notifications.disturb_option_a": "Non inviarmi notifiche push tra ", + "scenes.apps.account.notifications.disturb_option_b": " e ", + "scenes.apps.account.notifications.disturb_option_c": " (fuso orario locale)", + "scenes.apps.account.notifications.devices_subtitle": "Notifiche del dispositivo", + "scenes.apps.account.notifications.devices_option_ever": "Inviami sempre notifiche push", + "scenes.apps.account.notifications.devices_option_inactive": "Inviami notifiche push quando sono inattivo sul desktop", + "scenes.apps.account.notifications.devices_option_never": "Non inviarmi notifiche push mai", + "scenes.apps.account.notifications.privacy_subtitle": "Riservatezza", + "scenes.apps.account.notifications.mail_subtitle": "Notifiche di posta elettronica", + "scenes.apps.account.notifications.sound": "Notifica sonora", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Estensione", + "scenes.apps.parameters.workspace_sections.members.members": "Utenti", + "scenes.apps.parameters.workspace_sections.members.pending": "Email in attesa", + "scenes.apps.parameters.workspace_sections.members.invite": "Invita nuovo utente", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "Aggiungi utente", + "scenes.apps.tasks.boards": "Tavole", + "scenes.apps.tasks.connectors_menu": "Connettori...", + "scenes.apps.tasks.connectors_search_menu": "Cerchiamo connettori...", + "scenes.apps.tasks.no_connectors_menu_text": "Non disponi di connettori che possono connettersi a un calendario.", + "scenes.apps.tasks.unconfigured_tab": "Questa scheda non è ancora configurata.", + "scenes.apps.tasks.choose_board_button": "Scegli una tavola", + "scenes.apps.tasks.new_board.title": "Nuova tavola", + "scenes.apps.tasks.new_board.edit_title": "Modifica la tavola", + "scenes.apps.tasks.task": "Compito", + "scenes.apps.tasks.no_tasks": "Nessun compito", + "scenes.apps.tasks.task_status.todo": "Da fare", + "scenes.apps.tasks.task_status.current": "Attuale", + "scenes.apps.tasks.task_status.done": "Fatto", + "scenes.apps.tasks.task.description": "Descrizione", + "scenes.apps.tasks.task.assignees": "Assegnatari", + "scenes.apps.tasks.task.edit.dates": "Date", + "scenes.apps.tasks.list_modal.modify_list": "Modifica l'elenco", + "scenes.apps.tasks.list_modal.new_list": "Nuovo elenco", + "scenes.apps.tasks.list_modal.remove": "Rimuovi l'elenco ed i compiti", + "scenes.apps.tasks.list_modal.predefined_participants": "Partecipanti predefiniti", + "scenes.apps.tasks.list_modal.archive_all_tasks": "Archivia tutti i compiti", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Rimuovi i compiti archiviati ({{$1}})", + "scenes.login.footer.go_to_twake": "Vai su twakeapp.com", + "scenes.login.footer.branding": "Sei su un server Twake privato {{$1}} ({{$2}}). ", + "scenes.login.create_account.title": "Crea un nuovo account", + "scenes.login.create_account.email": "Posta elettronica", + "scenes.login.create_account.fill_in_email": "Devi compilare la tua email con una email corretta", + "scenes.login.create_account.too_short_password": "La tua password deve contenere almeno 8 caratteri.", + "scenes.login.create_account.firstname": "Nome", + "scenes.login.create_account.newsletter": "Ricevere informazioni su Twake", + "scenes.login.create_account.lastname": "Cognome", + "scenes.login.forgot_password.title": "Hai dimenticato la password?", + "scenes.login.forgot_password.text": "Riceverai un codice di 9 cifre via e-mail per verificare la tua identità.", + "scenes.login.forgot_password.email_to_recover": "E-mail da recuperare", + "scenes.login.forgot_password.mail_doesnt_exist": "Questa e-mail non esiste", + "scenes.login.forgot_password.text2": "Riceverai un codice di 9 cifre. Inseriscilo nel campo sottostante per continuare.", + "scenes.login.home.subtitle": "Benvenuto", + "scenes.login.home.email": "E-mail", + "scenes.login.home.unable_to_connect": "Credenziali non valide", + "scenes.login.home.password": "Password", + "scenes.login.home.login_btn": "Accedi", + "scenes.login.home.lost_password": "Hai dimenticato la password?", + "scenes.login.home.create_account": "Crea un account", + "scenes.login.create_account.password": "Password", + "scenes.login.create_account.step_2_subtitle_b": "Il tuo numero di telefono rimane privato.", + "scenes.login.create_account.step_3_mail_sent": "Ti abbiamo inviato un link di attivazione via e-mail.", + "scenes.login.create_account.step_3_subtitle": "Ultimo passaggio: dobbiamo verificare che non sei un robot!", + "scenes.app.workspaces.create_company.company_name.placeholder": "Nome dell'azienda", + "scenes.app.workspaces.create_company.company_name.title_1": "Per iniziare,", + "scenes.app.workspaces.create_company.company_name.title_2": "indica il nome della tua azienda.", + "scenes.app.workspaces.create_company.default_workspace_name": "Principale", + "scenes.app.workspaces.create_company.group_data.title": "Saremo veloci: abbiamo solo bisogno di alcune informazioni statistiche.", + "scenes.app.workspaces.create_company.importations.title_1": "Lavori già con strumenti digitali? Importa o integra subito i tuoi strumenti!", + "scenes.app.workspaces.create_company.importations.title_2": "Non preoccuparti, puoi farlo più tardi!", + "scenes.app.workspaces.create_company.invitations.title_2": "Aggiungi utenti al tuo team.", + "scenes.app.workspaces.create_company.title": "Crea la mia azienda", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "Aggiungi un'email secondaria", + "scenes.app.workspaces.welcome_page.added_to_company": "Sei stato invitato a ", + "scenes.app.workspaces.welcome_page.create_my_company": "Crea la mia azienda", + "scenes.app.workspaces.welcome_page.lets_go": "Andiamo!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Sei stato invitato utilizzando un altro email?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Oh, beh... Sembra che nessuno ti abbia ancora invitato in un'azienda.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Ora sei pronto a lavorare.", + "scenes.app.workspaces.welcome_page.see_you_soon": "A presto!", + "scenes.app.workspaces.welcome_page.try_again": "Riprova", + "scenes.app.workspaces.welcome_page.add_new_email": "Aggiungi una e-mail", + "scenes.app.workspaces.welcome_page.code_verification": "Codice di verifica", + "scenes.app.workspaces.welcome_page.new_email": "Aggiungi un'e-mail secondaria", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Ti abbiamo inviato un codice di verifica tramite {{$1}}", + "scenes.app.workspaces.welcome_page.done": "Ho finito", + "scenes.login.forgot_password.finished": "La tua password è stata aggiornata con successo.", + "scenes.apps.account.account.description_main": "Il tuo indirizzo principale è dove Twake invia le tue notifiche. I tuoi indirizzi secondari ti consentono di essere invitato automaticamente agli spazi di lavoro che li utilizzano.", + "scenes.apps.account.account.emails.description": "Gestisci i tuoi diversi indirizzi e-mail.", + "scenes.apps.account.account.make_main": "Imposta la e-mail principale", + "scenes.apps.account.account.password.description": "Cambia la tua password.", + "scenes.apps.account.identity": "Identità", + "scenes.apps.account.identity.description": "Modifica il tuo nome, cognome e immagine del profilo visibile agli altri utenti di Twake.", + "scenes.apps.account.preference": "Preferenze", + "scenes.apps.account.thumbnail.max_weight": "Dimensione massima 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "Conferma questa e-mail", + "app.name.twake_calendar": "Calendario", + "app.name.twake_drive": "Documenti", + "app.name.twake_tasks": "Compiti", + "components.calendar.repetition.everyday": "Quotidiano", + "components.calendar.repetition.does_not_repeat": "Non si ripete", + "components.calendar.repetition.weekly_on": "Settimanale il {{$1}}", + "components.calendar.repetition.monthly_on": "Mensile il {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Mensile il giorno {{$1}}", + "components.calendar.repetition.annually_on": "Annualmente il {{$1}}", + "components.calendar.repetition.every_weekday": "Tutti i giorni feriali (dal lunedì al venerdì)", + "components.calendar.repetition.custom": "Personalizzato...", + "components.calendar.repetition.repeat": "Ripetere ogni", + "components.calendar.repetition.ends": "Finisce", + "components.calendar.repetition.never": "Mai", + "components.calendar.repetition.on": "Il", + "components.calendar.repetition.after": "Dopo", + "components.calendar.repetition.days": "giorno/i", + "components.calendar.repetition.weeks": "settimana(e)", + "components.calendar.repetition.months": "mese(i)", + "components.calendar.repetition.years": "anno(i)", + "components.calendar.repetition.custom_recurrence": "Ricorrenza personalizzata", + "components.calendar.repetition.occurrence": "Evento(i)", + "components.calendar.repetition.repeat_on": "Ripetere il", + "scenes.app.channelsbar.currentuser.add_apps": "Cerchiamo applicazioni", + "scenes.app.channelsbar.currentuser.change_my_status": "Cambiare il mio stato", + "scenes.app.channelsbar.currentuser.collaborateurs": "Utenti", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Crea uno spazio di lavoro", + "scenes.app.channelsbar.currentuser.invited_status": "Sei un ospite.", + "scenes.app.channelsbar.currentuser.title": "Impostazioni dell 'account", + "scenes.app.channelsbar.currentuser.workspace_info": "Sei nello spazio di lavoro {{$1}} dal gruppo {{$2}}", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Impostazioni dello spazio di lavoro", + "scenes.app.channelsbar.currentuser.logout": "Esci", + "scenes.app.channelsbar.currentuser.update": "Aggiornare", + "scenes.app.channelsbar.currentuser.disable_notifications": "Disattivare", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Disattivare per 1h", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Disattivare fino alle 9:00 Domani", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Riattivare", + "scenes.app.channelsbar.currentuser.user_parameter": "Impostazioni di notifica", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Numero di messaggi", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "Nella versione gratuita di Twake, non è possibile accedere a più di {{$1}} messaggi più recenti.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Mostra più piani", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "Nuova discussione privata", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Nessun messaggio privato. Invita gli utenti!", + "scenes.app.channelsbar.channelsuser.private_messages": "Messaggi diretti", + "scenes.app.channelsbar.channelsworkspace.channel_title": "CANALI", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "PREFERITI", + "scenes.app.channelsbar.channelsworkspace.create_channel": "Crea un canale", + "scenes.app.channelsbar.channelsworkspace.no_channel": "Non ti sei ancora iscritto a nessun canale", + "scenes.app.channelsbar.modify_channel_menu": "Modifica canale", + "scenes.app.channelsbar.guest_management": "Gestione degli ospiti", + "scenes.app.channelsbar.unread_sign": "Segna come non letto", + "scenes.app.channelsbar.channel_leaving": "Lasciare il canale", + "scenes.app.channelsbar.channel_removing": "Eliminare il canale", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Puoi importare questi canali nella tua attività per rimanere organizzato facendo clic su questo riquadro.", + "scenes.app.channelsbar.company_invitation_alert_title": "Sei invitato in azienda ", + "scenes.app.channelsbar.initial_instructions_tutorial": "Scegli un nome, un cognome ed un'immagine del profilo.", + "scenes.app.channelsbar.installation_desktop_tutorial": "Installa l'applicazione desktop", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Invita gli utenti nel tuo spazio di lavoro.", + "scenes.app.channelsbar.public_channel_label": "Pubblico", + "scenes.app.channelsbar.private_channel_label": "Privato", + "scenes.app.channelsbar.sending_message_instruction": "Invia il tuo primo messaggio in una discussione", + "scenes.app.channelsbar.tutorial_alert": "Non mostrare più questa cornice mai?", + "scenes.app.channelsbar.welcome": "Benvenuto a Twake", + "scenes.app.channelsbar.welcoming_message_subtitle": "Diventa un professionista di Twake in pochi clic!", + "scenes.app.mainview.instruction_current_tab": "Inizia selezionando un canale alla tua sinistra.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Non hai un connettore in grado di connettersi a un canale.", + "scenes.app.mainview.tabs.rename": "Rinominare", + "scenes.app.mainview.tabs.searching_connectors": "Cerchiamo di connettori...", + "scenes.app.popup.adduser.adresses_message": "Si prega di separare gli indirizzi con una virgola o uno spazio. Ricorda che Twake può limitare il numero di inviti in base al tuo abbonamento.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Link di invito allo spazio di lavoro", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Copiato negli appunti con successo", + "scenes.app.popup.adduser.magiclinks.action_copy": "Copiare", + "scenes.app.popup.adduser.magiclinks.action_generate": "Creare", + "scenes.app.popup.appsparameters.pages._app_identity": "Identità dell'applicazione", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Prova l'aspetto dei tuoi messaggi Twacode", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "La mia fantastica app", + "scenes.app.popup.appsparameters.pages.api_data_description": "Dati utili per l'API Twake.", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "Impostazioni API", + "scenes.app.popup.appsparameters.pages.app_name_label": "Nome dell'applicazione", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Tutti i manager di questa azienda potranno modificare questa applicazione.", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Definisci cosa può modificare e leggere la tua applicazione.", + "scenes.app.popup.appsparameters.pages.app_update": "Aggiorna l'app {{$1}} (l'app viene utilizzata {{$2}} volte)", + "scenes.app.popup.appsparameters.pages.application_title": "Applicazione", + "scenes.app.popup.appsparameters.pages.apps_title": "Le tue applicazioni e connettori", + "scenes.app.popup.appsparameters.pages.automatique_label": "Automatico", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "Se attivi 'Automatico', questa applicazione verrà automaticamente aggiunta ai prossimi spazi di lavoro di questa azienda.", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "Indirizzi IP consentiti", + "scenes.app.popup.appsparameters.pages.create_app_button": "Crea un'applicazione", + "scenes.app.popup.appsparameters.pages.create_my_app": "Crea la mia applicazione", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Non hai ancora creato un'app. Prima di creare un'applicazione o un connettore, assicurati che non esista già nel nostro mercato delle applicazioni.", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "Elimina l'applicazione", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "Zona pericolosa", + "scenes.app.popup.appsparameters.pages.description_label": "Descrizione", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Applicazioni sviluppate dall'azienda", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Ti consente di definire dove sarà visibile la tua applicazione.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Impostazioni di visualizzazione", + "scenes.app.popup.appsparameters.pages.error_check_needed": "C'è stato un errore; controlla le tue informazioni.", + "scenes.app.popup.appsparameters.pages.error_message": "Questo nome è già utilizzato da un'altra applicazione; per favore scegline un altro.", + "scenes.app.popup.appsparameters.pages.error_user_code": "errore", + "scenes.app.popup.appsparameters.pages.event_subtitle": "Eventi", + "scenes.app.popup.appsparameters.pages.filter_information": "Questo filtro limita l'uso della tua chiave API ai soli server nel tuo connettore.", + "scenes.app.popup.appsparameters.pages.new_app_title": "Nuova applicazione", + "scenes.app.popup.appsparameters.pages.ok_user_code": "ok", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "L'applicazione non pubblicata funzionerà solo nella tua azienda. Se vuoi renderlo disponibile a tutti gli utenti Twake, attiva questa opzione.", + "scenes.app.popup.appsparameters.pages.public_login_label": "Identificatore pubblico", + "scenes.app.popup.appsparameters.pages.publication_description": "Determina la visibilità della tua applicazione.", + "scenes.app.popup.appsparameters.pages.publication_label": "Pubblicazione", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Pubblica l'applicazione", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Privilegi di lettura", + "scenes.app.popup.appsparameters.pages.remove_app": "Eliminare l'applicazione {{$1}} in modo permanente.", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Rimuovere da tutta l'azienda", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Rimuovi dallo spazio di lavoro", + "scenes.app.popup.appsparameters.pages.show_button": "Mostra", + "scenes.app.popup.appsparameters.pages.status_tilte": "Stato", + "scenes.app.popup.appsparameters.pages.string_information": "Questa stringa identifica la tua applicazione e verrà utilizzata nei comandi dei messaggi.", + "scenes.app.popup.appsparameters.pages.title_tester": "Tester di Twakecode", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "URL della ricezione degli eventi", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "In attesa...", + "scenes.app.popup.appsparameters.pages.website_label": "Sito web", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Privilegi di scrittura", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Non puoi eliminare questa app se è pubblicata.", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Il nome semplificato della tua applicazione è già utilizzato da un'altra applicazione. Per favore cambialo.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Si è verificato un errore durante l'aggiornamento dell'applicazione.", + "scenes.app.popup.appsparameters.pages.remove_app_button": "Elimina l'applicazione", + "scenes.app.popup.appsparameters.pages.update_button": "Aggiornare", + "scenes.app.popup.createworkspacepage.add_subtitle": "Bisogno di più spazio?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Crea un nuovo spazio di lavoro", + "scenes.app.popup.createworkspacepage.placeholder_name": "Nome dello spazio di lavoro", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Imposta la frequenza delle notifiche mobili.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Frequenza delle notifiche", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Evidenzia le seguenti parole chiave:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Imposta la frequenza delle notifiche e-mail.", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Mostra il contenuto dei messaggi privati", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Nascondi il contenuto dei messaggi privati", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Scegli un periodo durante il quale non ricevi notifiche.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Non disturbare di notte", + "scenes.app.popup.userparameter.pages.notif_content_label": "Contenuto delle notifiche", + "scenes.app.mainview.quick_search_placeholder": "Ricerca rapida", + "scenes.app.popup.userparameter.personnal_workspaces_title": "I tuoi spazi di lavoro", + "scenes.app.popup.workspaceparameter.admin_current_status": "Sei un amministratore.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Sei un amministratore dello spazio di lavoro.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Sei un amministratore dell'azienda.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Elimina lo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "La cancellazione di uno spazio di lavoro non può essere annullata. Tutti i messaggi e i file saranno irrecuperabili.", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Accedi alle tue applicazioni e ai tuoi connettori", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Integrazioni", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Cerchiamo di applicazioni", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Applicazioni di questo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Torna alla ricerca", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Invita utenti", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Utenti", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Applicazioni sviluppate dall'azienda", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Identità dell'azienda", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Cambia il nome di questa azienda", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "Nome dell 'azienda", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "configurazione", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Configura", + "scenes.app.popup.workspaceparameter.pages.description": "Descrizione", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Applicazioni sviluppate dall'azienda", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Preferenze di visualizzazione", + "scenes.app.popup.workspaceparameter.pages.install_button": "Installare", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Applicazioni installate in questo spazio di lavoro {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Applicazioni installate in altre aree dell'azienda {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Applicazioni installate", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Si è verificato un errore durante l'invito ai seguenti utenti: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Verifica che il nome utente o l'e-mail utilizzati siano validi.", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Modifica l'immagine di questo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Logo", + "scenes.app.popup.workspaceparameter.pages.name_description": "Cambia il nome di questo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.no_access": "Nessun accesso.", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "Non hai applicazioni in questo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Lascia questo spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Accesso in lettura", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Rimuovere da tutta l'azienda", + "scenes.app.popup.workspaceparameter.pages.research_by": "Cerca applicazioni per nome e categorie", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Cerchiamo di applicazioni...", + "scenes.app.popup.workspaceparameter.pages.show_button": "Schermo", + "scenes.app.popup.workspaceparameter.pages.title": "Impostazioni dello spazio di lavoro", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Accesso ai webhook", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Dimensione massima 5 MB.", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Rimuovi da questo spazio di lavoro", + "scenes.app.workspacesbar.components.create_company_menu": "Creare un'azienda", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} impostazioni", + "scenes.apps.calendar.add_calendar_menu": "Aggiungi un calendario", + "scenes.apps.calendar.connectors_menu": "Connettori...", + "scenes.apps.calendar.connectors_search_menu": "Cerchiamo di connettori...", + "scenes.apps.calendar.create_calendar_title": "Crea un calendario", + "scenes.apps.calendar.edit_calendar_title": "Modifica il calendario", + "scenes.apps.calendar.export_title": "Esportazione", + "scenes.apps.calendar.export_view_menu": "Esporta la vista...", + "scenes.apps.calendar.ics_download_menu": "Scarica un file ICS", + "scenes.apps.calendar.ics_subscription_menu": "Ottieni un link di abbonamento ICS", + "scenes.apps.calendar.modals.advanced_options": "Opzioni avanzate", + "scenes.apps.calendar.modals.event_title_placeholder": "Titolo", + "scenes.apps.calendar.modals.modify_event_button": "Modifica evento", + "scenes.apps.calendar.modals.part.participants": "Partecipanti", + "scenes.apps.calendar.modals.participants_event": "Partecipanti", + "scenes.apps.calendar.modals.reminders": "Promemoria", + "scenes.apps.calendar.modals.remove_button": "Eliminare", + "scenes.apps.calendar.modals.remove_event_button": "Elimina evento", + "scenes.apps.calendar.modals.remove_event_text": "Eliminare l'evento?", + "scenes.apps.calendar.modals.title_placeholder": "Titolo", + "scenes.apps.calendar.modify_calendar_menu": "Modifica il calendario", + "scenes.apps.calendar.month_option": "Mese", + "scenes.apps.calendar.my_calendar": "Il mio calendario", + "scenes.apps.calendar.my_calendar_label": "Il mio calendario", + "scenes.apps.calendar.my_calendar_menu": "Il mio calendario", + "scenes.apps.calendar.no_calendar_text": "Non hai impostato alcun calendario per questo spazio di lavoro.", + "scenes.apps.calendar.no_connectors_menu_text": "Non disponi di connettori che possono connettersi a un calendario.", + "scenes.apps.calendar.remove_calendar_confirmation": "Eliminare il calendario e i suoi eventi in modo permanente?", + "scenes.apps.calendar.today_menu": "Oggi", + "scenes.apps.calendar.week_option": "Settimana", + "scenes.apps.calendar.workspace": "Spazio di lavoro", + "scenes.apps.calendar.workspace_label": "Questo spazio di lavoro", + "scenes.apps.calendar.workspace_menu": "Spazio di lavoro", + "scenes.apps.drive.add_button": "Aggiungere", + "scenes.apps.drive.message_added_file": "{{$1}} ha inviato {{$2}}.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} ha inviato più file.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} ha inviato un file.", + "scenes.apps.drive.choose_folder_button": "Scegli una directory", + "scenes.apps.drive.choose_file_button": "Seleziona un file", + "scenes.apps.drive.create_folder_button": "Creare", + "scenes.apps.drive.download_button": "Scarica", + "scenes.apps.drive.open_link": "Aprire il link in una nuova finestra", + "scenes.apps.drive.files_subtitle": "File", + "scenes.apps.drive.folder_subtitle": "Cartelle", + "scenes.apps.drive.go_out_trash_menu": "Lascia il cestino", + "scenes.apps.drive.go_trash_menu": "Vai nel cestino", + "scenes.apps.drive.import_from_computer_menu": "Caricare dal computer", + "scenes.apps.drive.move_text": "Mossa", + "scenes.apps.drive.new_file_menu": "Nuovo file", + "scenes.apps.drive.new_file_title": "Nuovo file", + "scenes.apps.drive.new_external_storage": "Nuova memoria esterna", + "scenes.apps.drive.new_folder_title": "Nuova cartella", + "scenes.apps.drive.no_file_alert": "Non hai applicazioni che ti consentono di creare un file.", + "scenes.apps.drive.no_storage_app_alert": "Non hai applicazioni che ti consentono di aggiungere spazio di archiviazione esterno.", + "scenes.apps.drive.remove_definitely_menu": "Elimina definitivamente", + "scenes.apps.drive.restore_menu": "Ristabilire", + "scenes.apps.drive.throw_menu": "Invia nel cestino", + "scenes.apps.drive.trash_empty_menu": "Svuota il cestino", + "scenes.apps.drive.unconfigured_tab": "Questa scheda non è ancora configurata.", + "scenes.apps.drive.viewer.edit_with_button": "Modifica con {{$1}}", + "scenes.apps.drive.viewer.loading_preview_message": "Caricamento in corso...", + "scenes.apps.drive.viewer.no_preview_message": "Impossibile visualizzare questo tipo di file.", + "scenes.apps.drive.viewer.open_with_button": "Aperta con...", + "scenes.apps.messages.input.placeholder": "Scrivi un messaggio. Usa @ per citare un utente.", + "scenes.apps.messages.input.edited": "Modificato", + "scenes.apps.messages.just_you": "Visibile solo a te", + "scenes.apps.messages.message.new_messages_bar": "Nuovo messaggio", + "scenes.apps.messages.message.cancel_button": "Annulla", + "scenes.apps.messages.message.modify_button": "Modificare", + "scenes.apps.messages.message.pin_button": "Pin messaggio", + "scenes.apps.messages.message.unpin_button": "Sblocca messaggio", + "scenes.apps.messages.message.copy_link": "Copia il link al messaggio", + "scenes.apps.messages.message.pinned": "appuntato", + "scenes.apps.messages.message.remove_button": "Eliminare", + "scenes.apps.messages.message.reply_button": "Rispondere", + "scenes.apps.messages.message.save_button": "Salva", + "scenes.apps.messages.message.show_button": "Schermo", + "scenes.apps.messages.message.show_responses_button": "Visualizza tutte le risposte", + "scenes.apps.messages.message.types.first_channel_message_text": "Questo è il primo messaggio del canale", + "scenes.apps.messages.message.types.first_message_text": "Questo è il primo messaggio", + "scenes.apps.messages.messageslist.get_writing_user": "Sta scrivendo...", + "scenes.apps.messages.messageslist.get_writing_users": "stanno scrivendo...", + "scenes.apps.messages.messageslist.go_last_message_button": "Vai all'ultimo messaggio", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Nuovo messaggio", + "scenes.error_on_twake": "\"Houston abbiamo un problema\"", + "scenes.help_us": "Tuttavia, se desideri aiutarci a correggere questo errore, inviaci un messaggio di seguito: ", + "scenes.login.verifymail.alert": "Stiamo controllando la tua posta elettronica!", + "scenes.login.verifymail.error_message": "Si è verificato un errore", + "scenes.login.verifymail.signin_button": "Accesso", + "scenes.login.verifymail.success": "La tua e-mail è stata verificata con successo!", + "scenes.login.verifymail.verification_waiting": "In attesa di verifica...", + "scenes.no_panic": "Niente panico! Basta ricaricare questa pagina per correggere Twake.", + "services.apps.calendar.deadline_icon": "Scadenza", + "services.apps.calendar.event_icon": "Evento", + "services.apps.calendar.move_icon": "Mossa", + "services.apps.calendar.reminder_icon": "Promemoria", + "services.apps.messages.no_app": "Questa applicazione non esiste.", + "services.apps.messages.no_command_possible": "Non possiamo eseguire il comando '{{$1}}' perché '{{$2}}' non esiste o non consente di creare comandi.", + "services.user.notification_parameters_update_alert": "Le impostazioni di notifica sono state aggiornate.", + "services.user.update_password_alert": "La tua password è stata aggiornata.", + "scenes.app.workspaces.components.skip": "Saltare", + "scenes.apps.calendar.unconfigured_tab": "Questa scheda non è ancora configurata.", + "scenes.apps.drive.trash": "Spazzatura", + "scenes.apps.drive.top_menu_more": "Di più", + "scenes.apps.drive.top_menu_no_items": "{{$1}} elementi", + "scenes.apps.messages.new_thread": "Inizia una nuova discussione", + "scenes.apps.messages.input.send_message": "Invia messaggio", + "scenes.apps.messages.input.emoji": "emoji", + "scenes.apps.messages.input.hide_formatting": "Nascondi formattazione", + "scenes.apps.messages.input.show_formatting": "Mostra formattazione", + "scenes.tell_us": "Per favore dicci cosa stavi facendo a:", + "scenes.apps.drive.viewer.download_desktop": "Scarica Twak Desktop per l'anteprima nell'app", + "scenes.apps.tasks.my_tasks": "I miei compiti", + "scenes.apps.tasks.board.place_holder": "Nome del consiglio", + "scenes.apps.tasks.board.tasks.subtask": "Sottoattività", + "scenes.apps.tasks.board.tasks.add_subtask": "Aggiungi un'attività secondaria", + "scenes.apps.tasks.board.tasks.use_deadline": "Usa scadenza", + "scenes.apps.tasks.board.tasks.use_starttime": "Usa l'ora di inizio", + "scenes.apps.tasks.board.tasks.in_list": "nella lista", + "scenes.apps.tasks.board.starts": "inizia il", + "scenes.apps.tasks.board.ends": "Da fare per il", + "scenes.apps.tasks.board.list_name": "Lista nome", + "scenes.app.popup.sync_calendar": "Sincronizza i tuoi calendari.", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "Logo dell'azienda", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "Modifica l'immagine dell'azienda ", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "Annulla l'invito", + "scenes.apps.account.account.fullname": "Nome e cognome", + "login.email_login": "E-mail / Login", + "scenes.apps.account.account.password_for_user": "Password per il tuo utente", + "scenes.apps.account.account.send_info": "Invia queste informazioni sulle credenziali al tuo utente.", + "scenes.apps.account.account.save": "Salva account", + "scenes.apps.account.message_temporary": "Un account temporaneo funziona come un normale account Twake, ma crei la password e potrai reimpostarla se necessario.", + "scenes.apps.account.message_user_signin": "Il tuo utente può accedere in qualsiasi momento utilizzando la stessa e-mail e modificare l'account temporaneo in un account normale.", + "scenes.app.mainview.link_expired": "Questo collegamento pubblico non è valido o è scaduto.", + "scenes.app.mainview.create_account": "Crea il tuo spazio di lavoro gratuitamente su ", + "scenes.apps.calendar.modals.reminder_add": "Aggiungi un promemoria", + "scenes.apps.parameters.workspace_sections.members.invite_all": "Invita tutti", + "scenes.app.taskpicker.select": "Selezionare", + "components.listmanager.filter": "Filtro", + "scenes.apps.tasks.no_connector": "Nessun connettore", + "components.attachmentpicker.add_attachment": "Aggiungi allegati", + "components.input.copied": "copiato", + "components.drive.new_versions": "Aggiungi una nuova versione", + "components.drive.navigators.directory_not_found": "Directory non trovata.", + "components.drive.right_preview.suppress_link": "Sopprimere il collegamento", + "components.drive.right_preview.create_link": "Crea un link di accesso", + "components.drive.moove_here": "Vieni qui", + "components.drive.modify_uslist": "Modifica elenco utenti", + "components.tagpicker.tag_name": "Nome del tag", + "components.upload.drop_files": "Trascina qui i tuoi file", + "components.workspace.list_manager.no_workspace": "Nessuno spazio di lavoro", + "components.workspace.list_manager.add": "Aggiungi aree di lavoro", + "components.workspace.list_manager.current_space": "Area di lavoro attuale", + "components.workspace.list_manager.current_company": "Compagnia corrente", + "components.workspace.list_manager.all": "Tutto", + "components.workspace.calendar.invalid": "Non valido", + "components.searchpopup.enter_text": "Inserisci del testo per cercare Twak.", + "components.searchpopup.hide_filters": "nascondi filtri", + "components.searchpopup.show_filters": "mostra filtri", + "components.searchpopup.load_more": "Carica più risultati", + "general.more": "Di più", + "scenes.apps.board.archived_tasks": "Attività archiviate ({{$1}})", + "scenes.apps.board.active_tasks": "Compiti attivi", + "scenes.apps.board.kanban": "Kanban", + "scenes.apps.board.display_as": "Mostra come", + "scenes.apps.board.new_task": "+ Nuova attività", + "scenes.apps.board.all_boards": "Tutte le schede", + "components.userlistmanager.no_users": "Nessun utente.", + "scenes.apps.drive.used": "usato in questa cartella", + "components.reminder.notification": "Notifica", + "components.reminder.minutes_bef": "minuti prima", + "components.reminder.hours_bef": "ore prima", + "components.reminder.days_bef": "giorni prima", + "components.reminder.weeks_bef": "settimane prima", + "components.reminder.by_email": "E-mail", + "scenes.apps.calendar.reminders": "promemoria", + "scenes.apps.calendar.video_link": "Clicca per aprire il link", + "scenes.app.mainview.discussion": "Discussione", + "components.tagpicker.notag": "Nessun tag", + "scenes.apps.tasks.modals.attachments": "Allegati", + "components.calendar.calendarselector.from": "A partire dal", + "scenes.apps.drive.move_text2": "Mossa", + "components.attachmentpicker.from_computer": "Dal tuo dispositivo", + "components.attachmentpicker.from_twake": "Dai documenti Twak", + "components.attachmentpicker.file": "File", + "components.attachmentpicker.remove_attach": "Rimuovi allegato", + "scenes.apps.drive.remove_attachs": "Rimuovi allegati", + "components.drive.elements.see": "Vedere", + "components.drive.elements.current_name": "Nome corrente: ", + "scenes.app.popup.createcompany.try_again": "Per favore riprova.", + "scenes.app.popup.workspace.edit_temp": "Modifica account temporaneo", + "scenes.app.popup.workspace.create_temp": "Crea un account temporaneo", + "scenes.apps.tasks.active_tasks": "compiti attivi", + "scenes.apps.drive.right_preview.versions": "versioni", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Gestisci le tue applicazioni e i tuoi connettori.", + "scenes.app.popup.appsparameters.pages.icon": "Icona", + "scenes.app.popup.appsparameters.pages.title_informations": "Informazioni di base", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Informazioni relative alla gestione delle applicazioni", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "ID utente corrente", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "ID area di lavoro corrente", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "ID gruppo corrente", + "scenes.app.mainview.channel_description": "Descrivi il canale", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Invita automaticamente tutti gli utenti dell'area di lavoro a questo canale", + "scenes.client.channelbar.channelmemberslist.title": "Utenti in {{$1}}", + "scenes.client.channelbar.channelmemberslist.loader": "Carica di più", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Cerca utenti", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Rimuovi dal canale", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Crea un canale", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Unisciti a un canale", + "components.channelworkspacelist.title": "Canali", + "components.notifications.hidden_notifications_button.children": "Nuovo messaggio", + "components.newversion.new_version_component.row.part_1": "Stai utilizzando una versione Twake obsoleta", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} ha aggiunto un nuovo connettore {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} ha rimosso un connettore {{$2}}", + "components.alert.leave_private_channel.title": "Sei sicuro di voler lasciare il canale?", + "components.alert.leave_private_channel.description": "Non potrai più unirti a questo canale privato a meno che qualcuno non ti inviti.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Non sei un membro", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Carica di più", + "general.verify": "Verificare", + "components.unverified_account.typography_text_danger": "Si prega di verificare il tuo account entro {{$1}} giorni. In caso contrario, il tuo account verrà bloccato dopo 7 giorni e cancellato definitivamente dopo 30 giorni. Puoi verificare il tuo account attraverso l'email di verifica.", + "components.blocked_account.trial_period_over": "Il tuo periodo di prova è terminato. Per sbloccare il tuo account e ottenere l'accesso a tutte le funzionalità, verifica il tuo account tramite e-mail di conferma", + "components.add_mails_workspace.button": "Inizia a usare Twake", + "components.add_mails_workspace.title_1": "Aggiungi alcuni utenti", + "components.add_mails_workspace.title_2": "Twake è uno strumento di collaborazione in team, quindi invita alcuni utenti a testare uno spazio di lavoro che abbiamo creato per te.", + "components.add_mails_workspace.text_area_placeholder": "Inserisci le email dei tuoi utenti*", + "components.verify_mail.title_2": "Ora sei un utente ufficiale di Twake!", + "components.verify_mail.button": "Aggiungi utente", + "components.verify_mail.text": "Prima di tutto, devi verificare il tuo indirizzo email. Abbiamo inviato un link di verifica a", + "components.verify_mail.paragraph": "Puoi farlo in seguito, se lo desideri, ma gli account non verificati hanno accesso solo a una versione limitata di Twake", + "services.console_services.toaster.add_emails_error": "Errore durante l'aggiunta di email", + "services.console_services.toaster.add_email_error_message": "Errore durante l'aggiunta di {{$1}}", + "services.console_services.toaster.success_verify_email": "È stato inviato un collegamento di verifica al tuo account di posta elettronica", + "scenes.app.popup.workspaceparameter.edit_from_console": "Vedi in Console", + "services.console_services.toaster.success_invite_emails": "Utenti {{$1}} aggiunti con successo", + "scenes.client.channels_bar.modals.guest_management.title": "Gestisci gli ospiti in {{$1}}", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Cerca ospiti o email in attesa", + "scenes.client.channels_bar.modals.guest_management.tips": "Inizia ad aggiungere o cercare e-mail utilizzando l'input sopra", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Posta inviata", + "general.user.role.company.admin": "amministratore dell'azienda", + "general.user.role.company.member": "Membro", + "general.user.role.company.guest": "Ospite", + "general.user.deleted": "Account cancellato", + "components.richtexteditor.toolbar.bold": "Grassetto", + "components.richtexteditor.toolbar.underline": "Sottolineare", + "components.richtexteditor.toolbar.italic": "Corsivo", + "components.richtexteditor.toolbar.strikethrough": "barrato", + "components.richtexteditor.toolbar.unordered-list": "Elenco puntato", + "components.richtexteditor.toolbar.ordered-list": "Lista ordinata", + "components.richtexteditor.toolbar.blockquote": "citazione", + "components.richtexteditor.toolbar.code-block": "Blocco codice", + "components.locked_features.locked_history_banner.title": "Hai appena raggiunto il limite di messaggi", + "components.locked_features.locked_history_banner.description": "La tua azienda ha molti messaggi! Esegui l'upgrade ora per accedere a tutta la cronologia dei tuoi messaggi.", + "components.locked_features.locked_history_banner.button": "Scopri di più", + "components.locked_features.locked_guests_popup.title": "La funzione Ospiti è bloccata", + "components.locked_features.locked_guests_popup.subtitle": "Questa funzione non è disponibile nella versione gratuita di Twake", + "components.locked_features.locked_guests_popup.description": "Ops!! Sembra che tu voglia invitare utenti esterni nel tuo spazio di lavoro. Potresti prendere in considerazione l'upgrade del tuo piano se desideri collaborare con ospiti e partner esterni. Esplora le nostre opzioni di prezzo e seleziona l'opzione migliore per le esigenze di collaborazione del tuo team.", + "components.locked_features.locked_guests_popup.learn_more_button": "Scopri di più", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Salta per ora", + "components.locked_features.locked_guests_popup.or": "o", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Si è verificato un problema con l'abbonamento aziendale. Per favore, dai un'occhiata al tuo", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Si è verificato un problema con l'abbonamento aziendale. Si prega di contattare il proprietario o l'amministratore dell'azienda!", + "components.on_boarding.company_billing_banner.link": "piano di abbonamento aziendale", + "components.on_boarding.popups.blocked_company.title": "La tua azienda è bloccata a causa di un problema di pagamento", + "components.on_boarding.popups.blocked_company.description": "Il tuo abbonamento a Twake è scaduto. Contatta il proprietario o l'amministratore della tua azienda per rinnovarla ed essere in grado di comunicare nuovamente con il tuo team!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Vuoi saperne di più sul piano di abbonamento delle aziende?", + "scenes.apps.tasks.select_user_button": "Visualizza le attività di un altro utente", + "scenes.apps.messages.input.attach_file.from_computer": "Dal computer", + "scenes.app.popup.workspaceparameter.pages.table_title": "Nome", + "scenes.client.main_view.main_header.search_input": "Ricerca", + "scenes.apps.drive.new_link_title": "Nuovo collegamento", + "scenes.apps.drive.default_link_name": "Senza titolo", + "components.emoji_picker.input_search_placeholder": "Ricerca", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Non puoi aggiungere più di {{$2}} file in un messaggio", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Hai cancellato questo messaggio", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} ha cancellato il suo messaggio", + "components.member.user_parts.and_more_user_text": " e {{$1}} più utenti", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Crea un canale privato", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " invece", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Non puoi aggiungere più di 10 utenti", + "general.uploading": "Caricamento", + "components.upload.drop_files.toaster.error": "Non puoi caricare più di {{$1}} file", + "components.emoji_picker.categories.frequently_used": "Usato frequentemente", + "components.emoji_picker.categories.smileys_and_people": "Faccine e persone", + "components.emoji_picker.categories.animals_and_nature": "Animali e natura", + "components.emoji_picker.categories.food_and_drink": "Cibo bevanda", + "components.emoji_picker.categories.activity": "Attività", + "components.emoji_picker.categories.travel_and_places": "Viaggi e luoghi", + "components.emoji_picker.categories.objects": "oggetti", + "components.emoji_picker.categories.symbols": "Simboli", + "components.emoji_picker.categories.flags": "bandiere", + "components.emoji_picker.categories.search_result": "risultati di ricerca", + "components.emoji_picker.categories.not_found": "Nessun emoji trovato", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Ruolo", + "general.email": "E-mail", + "components.locked_features.locked_workspace_popup.title": "Non puoi creare più spazi di lavoro", + "components.locked_features.locked_workspace_popup.subtitle": "Nella versione gratuita, puoi avere un solo spazio di lavoro nella tua azienda.", + "components.locked_features.locked_workspace_popup.text": "Ops!! Vuoi creare un nuovo spazio di lavoro nella tua azienda? Potresti prendere in considerazione l'aggiornamento del tuo piano. Esplora le nostre opzioni di prezzo e seleziona la scelta migliore per le esigenze di collaborazione del tuo team.", + "components.locked_features.locked_only_office_popup.title": "Non puoi modificare questo file", + "components.locked_features.locked_only_office_popup.subtitle": "Nella versione gratuita, non puoi usare solooffice.", + "scenes.app.integrations_parameters.company_application_popup.tag": "Installato", + "scenes.app.integrations_parameters.company_application_popup.btn": "Installare", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Informazioni", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Descrizione", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Sito web", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Data di creazione", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Versione", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Spettacolo", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Rimuovere dall'azienda", + "scenes.app.integrations_parameters.company_applications_table.name": "Nome", + "scenes.app.integrations_parameters.company_applications_table.title": "Installato nella tua azienda", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Eliminato con successo {{$1}} dalla tua azienda", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Aggiunto con successo {{$1}} nella tua azienda", + "scenes.apps.messages.input.replied_to": "risposto a ", + "scenes.join.loading": "Caricamento in corso…", + "\"": "\"", + "login.create_account": "Creare un account", + "login.login_error": "Errore durante l'accesso", + "'": "'", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Nessuno ti ha ancora invitato in uno spazio di lavoro.", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Nessun utente trovato", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Nessuna emoji trovata", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Nessun comando trovato", + "scenes.apps.messages.message.types.no_message_in_thread": "Nessuno ha ancora risposto.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Area di lavoro predefinita", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Invita automaticamente tutti gli utenti dello spazio di lavoro a questo canale", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Stai per eliminare {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Hai ancora {{$1}} membri in {{$2}}. È necessario rimuovere tutti i membri per poter eliminare questo spazio di lavoro.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Comprendo che tutti i messaggi e i file del mio spazio di lavoro verranno eliminati.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "La dimensione massima del logo è 5mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Formato non valido, sono consentiti solo png, gif e jpg", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Errore sconosciuto", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Errore", + "scenes.app.channelsbar.currentuser.reset": "Ripristina", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Scrivi almeno tre lettere per visualizzare gli utenti", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} sta scrivendo...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} e {{$3}} altri utenti stanno scrivendo...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} e {{$2}} stanno scrivendo...", + "components.locked_features_components.locked_invite_alert.message_part_1": "La tua azienda ha raggiunto il limite massimo di membri {{$1}}. Per favore ", + "components.locked_features_components.locked_invite_alert.message_link": "migliora la tua azienda", + "components.locked_features_components.locked_invite_alert.message_part_2": " per invitare più membri.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " contatta il proprietario o l'amministratore della tua azienda.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Vedi tutti i membri della mia azienda sulla console", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Descrivi la tua candidatura in poche parole", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Nuova integrazione", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Comprendo che il proprietario e gli amministratori di questa azienda potranno modificare e pubblicare questa applicazione.", + "twake.application.access.title": "Seleziona gli ambiti giusti per la tua applicazione.", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Impostazioni dello sviluppatore", + "twake.application.access.no_default_scopes_available'": "Questa integrazione non ha alcun accesso {{$1}}.", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "la documentazione dell'API Twake", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Se non sai come riempirli, vai a ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Chiave privata", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Applicazione rimossa con successo {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Errore durante la rimozione dell'applicazione {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Applicazione {{$1}} riuscita!", + "scenes.app.integrations_parameters.add_application": "Nuova integrazione", + "components.rich_text_editor.plugins.suggestions.loading": "Alla ricerca di più", + "components.open_desktop_popup.subtitle": "aperto nell'app Twake", + "components.open_desktop_popup.open_here_link": "Apri qui invece", + "molecules.download_banner.title": "Ottieni il massimo da Twake, scarica subito l'app desktop", + "molecules.download_banner.download_button": "Scarica l'app desktop", + "scenes.app.channelsbar.channel_copy_link": "Copia il link del canale", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Aggiornato con successo", + "components.searchpopup.no_results_for": "Non ci sono risultati per", + "components.searchpopup.try_new_search": "Prova una nuova ricerca", + "components.searchpopup.chats": "Chat", + "components.searchpopup.all": "Tutti", + "components.searchpopup.media": "Media", + "components.searchpopup.files": "File", + "components.searchpopup.recent_chats": "Chat recenti", + "components.searchpopup.recent_media": "Media recenti", + "components.searchpopup.recent_files": "File recenti", + "components.searchpopup.recent_channels_and_contacts": "Canali e contatti recenti", + "components.searchpopup.header_title": "Cerca", + "components.searchpopup.scope.company": "in tutta compagnia", + "components.searchpopup.scope.channel": "in questo canale", + "components.searchpopup.channels": "Canali", + "components.searchpopup.messages": "Messaggi" +} diff --git a/twake/frontend/public/locales/ja.json b/twake/frontend/public/locales/ja.json index 32b7938b88..d71c6b8160 100644 --- a/twake/frontend/public/locales/ja.json +++ b/twake/frontend/public/locales/ja.json @@ -104,5 +104,807 @@ "scenes.login.home.login_btn": "ログイン", "scenes.login.home.lost_password": "パスワードをお忘れですか", "scenes.login.home.create_account": "アカウントを作成する", - "scenes.app.popup.appsparameters.pages.icon": "アイコン" -} \ No newline at end of file + "scenes.app.popup.appsparameters.pages.icon": "アイコン", + "scenes.apps.account.notifications.mail_subtitle": "電子メール通知", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "アプリケーションが編集および読み取りできるものを定義します。", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "次のイベントで送信されるパッシブデータ", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "未公開のアプリケーションは、あなたの会社でのみ機能します。すべてのTwakeユーザーが利用できるようにする場合は、このオプションを有効にします。", + "scenes.app.popup.appsparameters.pages.public_login_label": "公開識別子", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "公開されている場合、このアプリを削除することはできません。", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "アプリケーションの簡略名は、すでに別のアプリケーションで使用されています。変更してください。", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "アプリケーションの更新中にエラーが発生しました。", + "scenes.app.popup.createworkspacepage.placeholder_name": "ワークスペースの名前", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "モバイル通知の頻度を設定します。", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "通知の頻度", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "次のキーワードを強調表示します。", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "電子メール通知の頻度を設定します。", + "scenes.app.popup.userparameter.pages.private_message_content.show": "プライベートメッセージのコンテンツを表示する", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "通知を受け取らない期間を選択してください。", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "夜は邪魔しないでください", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "検索に戻る", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "ユーザーを招待する", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "会社が開発したアプリケーション", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "会社のアイデンティティ", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "この会社の名前を変更します", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "会社名", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "構成", + "scenes.app.popup.workspaceparameter.pages.configure_button": "構成、設定", + "scenes.app.popup.workspaceparameter.pages.description": "説明", + "scenes.app.popup.workspaceparameter.pages.name_label": "ワークスペースの名前", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "このワークスペースから削除します", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "ワークスペース", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "書き込みアクセス", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "アプリケーション", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "支払いとサブスクリプション", + "scenes.app.workspacesbar.components.change_company_title": "会社を変更する", + "scenes.app.workspacesbar.components.create_company_menu": "会社を作る", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}}設定", + "scenes.apps.calendar.connectors_menu": "コネクタ..。", + "scenes.apps.drive.new_file_menu": "新しいファイル", + "scenes.apps.drive.new_file_title": "新しいファイル", + "scenes.apps.drive.new_external_storage": "新しい外部ストレージ", + "scenes.apps.drive.new_folder_title": "新しいフォルダ", + "scenes.apps.drive.no_file_alert": "ファイルを作成できるアプリケーションはありません。", + "scenes.apps.drive.no_storage_app_alert": "外部ストレージを追加できるアプリケーションはありません。", + "scenes.apps.drive.remove_definitely_menu": "完全に削除する", + "scenes.apps.drive.restore_menu": "戻す", + "scenes.apps.drive.throw_menu": "ゴミ箱に送る", + "scenes.apps.drive.trash_empty_menu": "ゴミ箱を空にする", + "scenes.apps.drive.unconfigured_tab": "このタブはまだ構成されていません。", + "scenes.apps.messages.message.unpin_button": "メッセージの固定を解除する", + "scenes.apps.messages.message.copy_link": "メッセージへのリンクをコピー", + "scenes.no_panic": "慌てる必要はありません!このページをリロードするだけでTwakeを修正できます。", + "services.apps.calendar.event_icon": "イベント", + "services.apps.calendar.move_icon": "動く", + "services.apps.calendar.reminder_icon": "リマインダー", + "services.apps.messages.no_app": "このアプリケーションは存在しません。", + "services.apps.messages.no_command_possible": "'{{$2}}'が存在しないか、コマンドの作成が許可されていないため、コマンド '{{$1}}'を実行できません。", + "services.user.notification_parameters_update_alert": "通知設定が更新されました。", + "services.user.update_password_alert": "パスワードが更新されました。", + "scenes.app.workspaces.components.skip": "スキップ", + "scenes.apps.calendar.unconfigured_tab": "このタブはまだ構成されていません。", + "scenes.apps.drive.trash": "ごみ", + "components.add_mails_workspace.title_1": "一部のユーザーを追加", + "components.add_mails_workspace.title_2": "Twakeはチームコラボレーションツールなので、私たちが作成したワークスペースをテストするために何人かのユーザーを招待します。", + "components.add_mails_workspace.text_area_placeholder": "ユーザーのメールアドレスを入力してください*", + "components.verify_mail.title_1": "おめでとう", + "components.verify_mail.title_2": "あなたは今、Twakeの公式ユーザーです!", + "services.console_services.toaster.add_emails_error": "メールの追加中にエラーが発生しました", + "services.console_services.toaster.add_email_error_message": "{{$1}}の追加中にエラーが発生しました", + "components.richtexteditor.toolbar.code-block": "コードブロック", + "components.locked_features.locked_history_banner.title": "メッセージ制限に達しました", + "components.locked_features.locked_history_banner.button": "もっと詳しく知る", + "components.locked_features.locked_guests_popup.title": "ゲスト機能はロックされています", + "components.locked_features.locked_guests_popup.subtitle": "この機能は、Twake無料バージョンでは使用できません", + "components.locked_features.locked_guests_popup.description": "おっと!外部ユーザーをワークスペースに招待したいようです。ゲストや外部パートナーとコラボレーションしたい場合は、プランのアップグレードを検討することをお勧めします。価格設定オプションを調べて、チームコラボレーションのニーズに最適なオプションを選択してください。", + "components.locked_features.locked_guests_popup.learn_more_button": "もっと詳しく知る", + "components.locked_features.locked_guests_popup.skip_for_now_button": "今すぐスキップ", + "components.locked_features.locked_guests_popup.or": "または", + "components.on_boarding.popups.blocked_company.company_selector": "別の会社に切り替える", + "scenes.apps.tasks.select_user_button": "他のユーザーのタスクを表示する", + "scenes.apps.messages.input.attach_file.from_computer": "コンピューターから", + "scenes.app.popup.workspaceparameter.pages.table_title": "名前", + "scenes.client.main_view.main_header.search_input": "検索", + "scenes.apps.drive.new_link_title": "新しいリンク", + "scenes.apps.drive.default_link_name": "無題", + "components.emoji_picker.input_search_placeholder": "検索", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}}-メッセージに{{$2}}を超えるファイルを追加することはできません", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "このメッセージを削除しました", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}}は彼のメッセージを削除しました", + "components.member.user_parts.and_more_user_text": " および{{$1}}より多くのユーザー", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "プライベートチャネルを作成する", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " 代わりは", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "10人を超えるユーザーを追加することはできません", + "general.uploading": "アップロード", + "components.upload.drop_files.toaster.error": "{{$1}}を超えるファイルをアップロードすることはできません", + "components.emoji_picker.categories.frequently_used": "よく使う", + "components.emoji_picker.categories.animals_and_nature": "動物と自然", + "components.emoji_picker.categories.food_and_drink": "食べ物飲み物", + "components.locked_features.locked_workspace_popup.text": "おっと!会社に新しいワークスペースを作成しますか?計画のアップグレードを検討することをお勧めします。価格設定オプションを調べて、チームコラボレーションのニーズに最適な選択肢を選択してください。", + "components.locked_features.locked_only_office_popup.text": "おっと! Twakeからファイルを編集したいようです。 Officeファイルを中心に共同作業を行う場合は、プランのアップグレードを検討することをお勧めします。価格設定オプションを調べて、チームコラボレーションのニーズに最適なオプションを選択してください。", + "components.locked_features.locked_drive_popup.title": "ドライブ制限に達しました", + "components.locked_features.locked_drive_popup.subtitle": "無料版では、6GBしか保存できません。", + "scenes.app.integrations_parameters.title": "統合", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "見せる", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "会社から削除する", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "再アクティブ化", + "scenes.join.login_first_button": "最初にログインするか、アカウントを作成してください", + "scenes.join.join_the_team_button": "チームに参加する", + "scenes.apps.account.account.save": "アカウントを保存", + "scenes.apps.tasks.board.list_name": "リスト名", + "scenes.apps.calendar.workspace_label": "このワークスペース", + "scenes.app.popup.appsparameters.pages.update_button": "アップデート", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "使用したユーザー名または電子メールが有効であることを確認してください。", + "components.calendar.repetition.occurrence": "発生(s)", + "general.retry": "リトライ", + "scenes.app.popup.appsparameters.pages.show_button": "見せる", + "scenes.apps.calendar.no_connectors_menu_text": "カレンダーに接続できるコネクタがありません。", + "components.emoji_picker.categories.smileys_and_people": "Smileys&People", + "components.locked_features.locked_history_banner.description": "あなたの会社にはたくさんのメッセージがあります!今すぐアップグレードして、すべてのメッセージ履歴にアクセスしてください。", + "scenes.app.workspaces.create_company.title": "私の会社を作る", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "ユーザー", + "scenes.app.popup.appsparameters.pages.app_name_label": "アプリケーション名", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}}はチャネルから{{$2}}を削除しました", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}、{{$2}}、{{$3}}", + "components.searchpopup.tags": "タグ", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "機械/自動車", + "general.help.documentation": "ドキュメンテーション", + "general.connexion_status.connected": "あなたはオンラインです", + "general.update": "アップデート", + "general.send": "メッセージを送る", + "general.unarchive": "アーカイブ解除", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "アプリケーション特権", + "scenes.login.create_account.step_2_subtitle_b": "あなたの電話番号は非公開のままです。", + "scenes.login.create_account.step_3_mail_sent": "アクティベーションリンクをメールでお送りしました。", + "general.add": "追加", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "銀行/保険", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "IT /テレコム", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "研究とアドバイス", + "general.connexion_status.disconnected": "オフラインです", + "components.locked_features.locked_workspace_popup.subtitle": "無料版では、会社にワークスペースを1つだけ含めることができます。", + "application.load.longer": "サーバーが応答するのに予想よりも時間がかかります。しばらく待つか、ページをリロードしてください...", + "scenes.app.workspaces.create_company.group_data": "新しいグループを構成します", + "scenes.app.workspaces.create_company.group_data.group_type": "グループタイプ", + "scenes.app.workspaces.create_company.group_data.group_type.company": "会社または会社の部門", + "scenes.app.workspaces.create_company.group_data.group_type.public_organization": "公的機関", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "社会、クラブまたは慈善団体", + "scenes.app.workspaces.create_company.group_data.group_type.other_group": "他の", + "scenes.app.workspaces.create_company.group_data.group_size": "グループサイズ", + "scenes.app.workspaces.create_company.group_data.group_size.less_3": "4人未満のユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4〜10人のユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11〜49人のユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50〜99人のユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100〜499ユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500〜999ユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000〜4999ユーザー", + "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "5000人以上のユーザー", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "主な活動", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "食べ物", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "印刷/紙", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "建設/建材", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "不動産", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "化学", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "貿易/商取引/流通", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "出版/コミュニケーション/マルチメディア", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "製薬業界", + "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "ビジネスサービス", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "エンターテイメント", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "テキスタイル/衣類/靴", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "輸送/ロジスティクス", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "リサーチ", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "教育", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "管理", + "scenes.app.workspaces.create_company.invitations.title": "ワークスペースを構成します。", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "お気に入りから削除", + "scenes.apps.messages.left_bar.stream.notifications": "通知...", + "scenes.apps.messages.left_bar.stream.notifications.all": "メッセージ", + "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}}のみ", + "scenes.apps.messages.left_bar.stream.notifications.never": "何もない", + "scenes.apps.account.notifications.sound": "音声通知", + "scenes.apps.tasks.connectors_menu": "コネクタ..。", + "scenes.apps.tasks.connectors_search_menu": "コネクタを検索...", + "scenes.apps.tasks.no_connectors_menu_text": "カレンダーに接続できるコネクタがありません。", + "scenes.apps.tasks.unconfigured_tab": "このタブはまだ構成されていません。", + "scenes.apps.tasks.choose_board_button": "ボードを選択してください", + "scenes.apps.tasks.new_board.title": "新しいボード", + "scenes.apps.tasks.new_board.edit_title": "ボードを編集", + "scenes.apps.tasks.task_status.todo": "する", + "scenes.apps.tasks.task_status.done": "終わり", + "scenes.apps.tasks.task.description": "説明", + "scenes.apps.tasks.task.assignees": "譲受人", + "scenes.apps.tasks.task.edit.dates": "日付", + "scenes.apps.tasks.list_modal.modify_list": "リストを変更", + "scenes.apps.tasks.list_modal.new_list": "新しいリスト", + "scenes.apps.tasks.list_modal.remove": "リストとタスクを削除する", + "scenes.apps.tasks.list_modal.predefined_participants": "事前定義された参加者", + "scenes.apps.tasks.list_modal.archive_all_tasks": "すべてのタスクをアーカイブする", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "アーカイブされたタスクを削除する({{$1}})", + "scenes.login.footer.branding": "{{$1}}({{$2}})プライベートTwakeサーバーを使用しています。 ", + "scenes.login.create_account.newsletter": "Twakeに関する情報を受け取る", + "scenes.login.home.subtitle": "お会いできて嬉しいです", + "scenes.login.create_account.password": "パスワード", + "scenes.login.create_account.step_1_subtitle": "これ以上簡単なことはありません—必要なのはいくつかの情報だけです。", + "scenes.login.create_account.step_2_subtitle_a": "他のユーザーがあなたを認識できるように、フルネームを追加します。", + "scenes.login.create_account.step_3_subtitle": "最後のステップ—あなたがロボットではないことを確認する必要があります!", + "scenes.app.workspaces.create_company.company_name.placeholder": "会社名", + "scenes.app.workspaces.create_company.company_name.title_2": "あなたの会社の名前を示してください。", + "scenes.app.workspaces.create_company.default_workspace_name": "主要", + "scenes.app.workspaces.create_company.importations.title_1": "すでにデジタルツールを使用していますか?今すぐツールをインポートまたは統合してください!", + "scenes.app.workspaces.create_company.importations.title_2": "心配ありません。後でこれを行うことができます。", + "scenes.app.workspaces.create_company.invitations.title_2": "チームにユーザーを追加します。", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "予備のメールを追加する", + "scenes.app.workspaces.welcome_page.added_to_company": "あなたはに招待されました ", + "scenes.app.workspaces.welcome_page.create_my_company": "私の会社を作る", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "別のメールアドレスを使用して招待されましたか?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "ああ、まあ...まだ誰もあなたをワークスペースに招待していないようです。", + "scenes.app.workspaces.welcome_page.ready_to_work": "これで作業する準備が整いました。", + "scenes.app.workspaces.welcome_page.try_again": "再試行", + "scenes.app.workspaces.welcome_page.twake_team": "トウェイク", + "scenes.app.workspaces.welcome_page.welcome_header": "Twakeへようこそ!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "複数の電子メールアドレスをアカウントにリンクできます。通知の送信に使用されるアドレスは1つだけです。", + "scenes.app.workspaces.welcome_page.main_mail_title": "メインアドレス", + "scenes.app.workspaces.welcome_page.other_mail_title": "セカンダリアドレス", + "scenes.app.workspaces.welcome_page.add_new_email": "電子メールを追加する", + "scenes.app.workspaces.welcome_page.code_verification": "検証コード", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "{{$1}}経由で確認コードをお送りしました", + "scenes.login.forgot_password.finished": "パスワードは正常に更新されました。", + "scenes.apps.account.account.description_main": "メインアドレスは、Twakeが通知を送信する場所です。セカンダリアドレスを使用すると、それらを使用するワークスペースに自動的に招待されます。", + "scenes.apps.account.account.emails.description": "さまざまな電子メールアドレスを管理します。", + "scenes.apps.account.account.password.description": "パスワードを変更してください。", + "scenes.apps.account.identity.description": "他のTwakeユーザーに表示される名前、名前、プロフィール画像を変更します。", + "scenes.apps.account.preference": "環境設定", + "general.open": "開ける", + "scenes.apps.account.thumbnail.max_weight": "最大サイズ5MB", + "scenes.apps.account.account.email_add_modal.confirm": "このメールを確認してください", + "app.name.twake_calendar": "カレンダー", + "app.name.twake_drive": "ドキュメント", + "app.name.twake_tasks": "タスク", + "components.calendar.repetition.everyday": "毎日", + "components.calendar.repetition.does_not_repeat": "繰り返さない", + "components.calendar.repetition.weekly_on": "毎週{{$1}}", + "components.calendar.repetition.monthly_on": "{{$1}} {{$2}}で毎月", + "components.calendar.repetition.annually_on": "毎年{{$1}}", + "components.calendar.repetition.every_weekday": "平日(月〜金)", + "components.calendar.repetition.custom": "カスタム...", + "components.calendar.repetition.repeat": "毎回繰り返す", + "components.calendar.repetition.never": "一度もない", + "components.calendar.repetition.on": "オン", + "components.calendar.repetition.after": "後", + "components.calendar.repetition.months": "月", + "components.calendar.repetition.years": "年", + "components.calendar.repetition.custom_recurrence": "カスタム再発", + "components.calendar.repetition.repeat_on": "繰り返します", + "scenes.app.channelsbar.currentuser.add_apps": "アプリケーションの検索", + "scenes.app.channelsbar.currentuser.change_my_status": "ステータスを変更する", + "scenes.app.channelsbar.currentuser.collaborateurs": "ユーザー", + "scenes.app.channelsbar.currentuser.create_workspace_page": "ワークスペースを作成する", + "scenes.app.channelsbar.currentuser.invited_status": "あなたはゲストです。", + "scenes.app.channelsbar.currentuser.workspace_info": "グループ{{$2}}のワークスペース{{$1}}にいます", + "scenes.app.channelsbar.currentuser.workspace_parameters": "ワークスペース設定", + "scenes.app.channelsbar.currentuser.logout": "サインアウト", + "scenes.app.channelsbar.currentuser.update": "アップデート", + "scenes.app.channelsbar.currentuser.disable_notifications": "無効にする", + "scenes.app.channelsbar.currentuser.disabling_notifications": "1時間無効にする", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "午前9時まで無効にする明日", + "scenes.app.channelsbar.currentuser.user_parameter": "通知設定", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "書き込み権限", + "scenes.app.channelsbar.company_invitation_alert_title": "あなたは会社に招待されています ", + "scenes.app.channelsbar.initial_instructions_tutorial": "名、名前、プロフィール写真を選択します。", + "scenes.app.channelsbar.installation_desktop_tutorial": "デスクトップアプリケーションをインストールします", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "ユーザーをワークスペースに招待します。", + "scenes.app.channelsbar.public_channel_label": "公衆", + "scenes.app.channelsbar.sending_message_instruction": "ディスカッションで最初のメッセージを送信する", + "scenes.app.channelsbar.tutorial_alert": "このフレームを二度と表示しませんか?", + "scenes.app.channelsbar.welcome": "Twakeへようこそ", + "scenes.app.channelsbar.welcoming_message_subtitle": "数回クリックするだけでTwakeプロになりましょう!", + "scenes.app.mainview.instruction_current_tab": "左側のチャンネルを選択することから始めます。", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "チャネルに接続できるコネクタがありません。", + "scenes.app.mainview.tabs.rename": "名前を変更", + "scenes.app.mainview.tabs.searching_connectors": "コネクタを検索...", + "scenes.app.popup.adduser.adresses_message": "アドレスはカンマまたはスペースで区切ります。 Twakeは、サブスクリプションに基づいて招待の数を制限できることに注意してください。", + "scenes.app.popup.appsparameters.pages._app_identity": "アプリケーションのID", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Twacodeメッセージの外観をテストします", + "scenes.app.popup.appsparameters.pages.alert_published_app": "アプリケーションは公開されています。編集することはできません。", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "開発時に*を使用して、すべてのIPアドレスを許可します。", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "私の素晴らしいアプリ", + "scenes.app.popup.appsparameters.pages.api_data_description": "TwakeAPIに役立つデータ。", + "scenes.apps.calendar.no_calendar_text": "このワークスペースにカレンダーを設定していません。", + "scenes.apps.calendar.remove_calendar_confirmation": "カレンダーとそのイベントを完全に削除しますか?", + "scenes.app.mainview.advanced_search_placeholder": "高度な検索", + "components.searchpopup.hide_filters": "フィルタを非表示にする", + "components.searchpopup.show_filters": "フィルタを表示", + "components.searchpopup.load_more": "より多くの結果をロードする", + "general.more": "もっと", + "scenes.app.popup.adduser.magiclinks.genrator_info": "ワークスペースへの招待リンク", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "新しいリンクが生成されました", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "クリップボードに正常にコピーされました", + "scenes.app.popup.adduser.magiclinks.action_copy": "コピー", + "scenes.app.popup.adduser.magiclinks.action_generate": "生成", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "API設定", + "scenes.app.popup.appsparameters.pages.app_modification_right": "この会社のすべてのマネージャーは、このアプリケーションを編集できます。", + "scenes.app.popup.appsparameters.pages.filter_information": "このフィルターは、APIキーの使用をコネクター内のサーバーのみに制限します。", + "scenes.app.popup.appsparameters.pages.installation": "インストール。", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "まず、メッセージをJSON形式で記述します。", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "内部アプリケーション", + "scenes.app.popup.appsparameters.pages.loading": "読み込んでいます...", + "scenes.app.popup.appsparameters.pages.modify_public_data": "アプリケーションの公開データを編集します。", + "scenes.app.popup.appsparameters.pages.new_app_title": "新しいアプリ", + "scenes.app.popup.appsparameters.pages.ok_user_code": "わかった", + "scenes.app.popup.appsparameters.pages.optimal_format": "最適なフォーマット:48x48px。", + "scenes.app.popup.appsparameters.pages.public_availability_application": "公開アプリケーション", + "scenes.app.popup.appsparameters.pages.remove_app_button": "アプリケーションを削除する", + "scenes.app.popup.createworkspacepage.add_subtitle": "より多くのスペースが必要ですか?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "新しいワークスペースを作成します", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "統合", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "表示設定", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "ロゴ", + "scenes.app.popup.workspaceparameter.pages.name_description": "このワークスペースの名前を変更します", + "scenes.apps.drive.viewer.edit_with_button": "{{$1}}で編集", + "scenes.apps.drive.viewer.loading_preview_message": "読み込んでいます...", + "scenes.apps.messages.message.new_messages_bar": "新しいメッセージ", + "scenes.apps.messages.message.cancel_button": "キャンセル", + "scenes.apps.messages.message.modify_button": "編集", + "scenes.apps.messages.message.pin_button": "ピンメッセージ", + "components.verify_mail.text": "まず、メールアドレスを確認する必要があります。に確認リンクを送信しました", + "components.verify_mail.paragraph": "必要に応じて後で行うことができますが、未確認のアカウントは限定バージョンのTwakeにしかアクセスできません", + "components.richtexteditor.toolbar.blockquote": "ブロッククォート", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "会社のサブスクリプションに問題があります。どうぞ、あなたの", + "components.on_boarding.company_billing_banner.guest_or_member_text": "会社のサブスクリプションに問題があります。会社の所有者または管理者に連絡してください!", + "components.on_boarding.company_billing_banner.link": "会社のサブスクリプションプラン", + "components.on_boarding.popups.blocked_company.description": "Twakeのサブスクリプションの有効期限が切れています。会社の所有者または管理者に連絡して更新し、チームと再度連絡できるようにしてください。", + "components.on_boarding.popups.blocked_company.learn_more_text": "企業のサブスクリプションプランについてもっと知りたいですか?", + "components.on_boarding.popups.blocked_company.or": "または", + "scenes.apps.tasks.select_user": "ユーザーを検索", + "components.emoji_picker.categories.activity": "アクティビティ", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "役割", + "general.email": "Eメール", + "components.locked_features.locked_only_office_popup.title": "このファイルは編集できません", + "components.locked_features.locked_only_office_popup.subtitle": "無料版では、officeのみは使用できません。", + "scenes.app.integrations_parameters.applications_table.name": "名前", + "scenes.app.integrations_parameters.applications_table.title": "その他の統合", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "検索アプリケーション", + "scenes.app.integrations_parameters.company_application_popup.tag": "インストール済み", + "scenes.app.integrations_parameters.company_application_popup.btn": "インストール", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "情報", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "説明", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Webサイト", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "作成日", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "バージョン", + "scenes.app.integrations_parameters.company_applications_table.name": "名前", + "scenes.app.integrations_parameters.company_applications_table.title": "あなたの会社にインストールされています", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "会社から{{$1}}を正常に削除しました", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "あなたの会社に{{$1}}が正常に追加されました", + "scenes.apps.messages.input.replied_to": "に返信 ", + "components.workspace.list_manager.all": "全て", + "general.help": "ヘルプ", + "scenes.apps.drive.go_out_trash_menu": "ゴミを残す", + "components.account_verification_status_sentence": "アカウントのステータスは次のとおりです:{{$1}}", + "scenes.apps.tasks.no_tasks": "聞かない", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "この名前は、別のアプリケーションですでに使用されています。別のものを選択してください。", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "簡略名", + "scenes.apps.messages.message.pinned": "固定", + "general.user.role.company.member": "メンバー", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "プライベートメッセージのコンテンツを非表示にする", + "scenes.apps.messages.message.show_button": "画面", + "scenes.apps.messages.messageslist.get_writing_users": "書いています...", + "login.email_login": "Eメール/ログイン", + "scenes.app.channelsbar.unread_sign": "未読としてマーク", + "scenes.app.popup.userparameter.personnal_workspaces_title": "あなたのワークスペース", + "scenes.apps.calendar.add_calendar_menu": "カレンダーを追加する", + "scenes.apps.drive.top_menu_more": "もっと", + "scenes.apps.drive.top_menu_no_items": "【X0X】アイテム", + "scenes.join.loading": "読み込んでいます…", + "scenes.join.wrong_link_title": "このリンクはもう利用できません", + "scenes.join.wrong_link_description": "あなたをこの会社に招待した人に新しいリンクを求めるか、あなた自身の会社を作りましょう", + "scenes.join.create_the_company_button": "会社を作る", + "scenes.join.join_workspace_from_company": "{{$2}}から{{$1}}に参加しましょう!", + "scenes.join.twake_description": "Twakeは、チームの生産性を向上させるために構築されたオープンソースのデジタルワークスペースです。", + "scenes.app.workspaces.create_company.company_name.title_1": "始める、", + "scenes.apps.account.account.make_main": "メインを設定", + "components.verify_mail.button": "ユーザーを追加する", + "services.apps.calendar.deadline_icon": "締め切り", + "components.calendar.repetition.days": "日々)", + "scenes.app.workspaces.welcome_page.see_you_soon": "また近いうちにお会いしましょう!", + "scenes.app.workspaces.welcome_page.new_email": "予備の電子メールを追加する", + "components.calendar.repetition.ends": "終了", + "components.on_boarding.popups.blocked_company.title": "あなたの会社は支払いの問題のためにロックされています", + "scenes.app.popup.workspaceparameter.pages.no_access": "アクセスなし。", + "components.users_picker.add_me": "私を追加してください", + "scenes.apps.drive.right_preview.public": "パブリック・アクセス", + "scenes.apps.calendar.modals.event_description_placeholder": "説明", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "会社が開発したアプリケーション", + "scenes.apps.drive.right_preview.public_link": "パブリックリンク", + "scenes.apps.account.identity": "身元", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "アプリケーションとコネクタを管理します。", + "scenes.app.channelsbar.currentuser.title": "アカウント設定", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "ドキュメントに移動して、JSON形式で構成を生成します。", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "あなたはワークスペース管理者です。", + "scenes.app.channelsbar.private_channel_label": "プライベート", + "scenes.app.workspaces.welcome_page.lets_go": "さあ行こう!", + "scenes.apps.tasks.task_status.current": "現在", + "scenes.apps.tasks.board.tasks.in_list": "リストに", + "components.calendar.repetition.weeks": "週", + "scenes.apps.drive.go_trash_menu": "ゴミ箱に行く", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "許可されたIPアドレス", + "scenes.apps.calendar.video_link": "クリックしてリンクを開く", + "components.calendar.repetition.monthly_on_day": "毎月当日{{$1}}", + "general.connexion_status.connecting": "再接続しています…", + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "材料", + "scenes.apps.tasks.boards": "ボード", + "general.remove": "削除する", + "scenes.app.side_app.messages_thread_title": "{{$1}}•メッセージスレッド", + "scenes.app.workspaces.create_company.group_data.group_type.university_school": "大学または学校", + "general.help.support": "サポート", + "general.archive": "アーカイブ", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "エレクトロニクス/電気/エネルギー", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "お気に入りに追加", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "他の", + "components.locked_features.locked_workspace_popup.title": "これ以上ワークスペースを作成することはできません", + "components.searchpopup.size": "サイズ", + "general.resume": "履歴書", + "general.pause": "一時停止", + "scenes.app.workspaces.welcome_page.done": "私はこれで終わりです", + "scenes.apps.tasks.task": "タスク", + "scenes.app.workspaces.create_company.group_data.title": "迅速に対応します—必要なのは統計情報だけです。", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "メッセージ番号", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "無料版のTwakeでは、{{$1}}より新しいメッセージにアクセスすることはできません。", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "より多くの計画を表示する", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "新しいプライベートディスカッション", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "プライベートメッセージはありません。ユーザーを招待しましょう!", + "scenes.app.channelsbar.channelsuser.private_messages": "ダイレクトメッセージ", + "scenes.app.channelsbar.channelsworkspace.channel_title": "チャンネル", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "お気に入り", + "scenes.app.channelsbar.channelsworkspace.create_channel": "チャネルを作成する", + "scenes.app.channelsbar.channelsworkspace.no_channel": "まだどのチャンネルにも参加していません", + "scenes.app.channelsbar.modify_channel_menu": "チャンネルを編集", + "scenes.app.channelsbar.guest_management": "ゲスト管理", + "scenes.app.channelsbar.read_sign": "既読にする", + "scenes.app.channelsbar.channel_leaving": "チャネルを離れる", + "scenes.app.channelsbar.channel_removing": "チャネルを削除", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "このフレームをクリックすると、これらのチャネルをビジネスにインポートして、整理された状態を保つことができます。", + "scenes.app.popup.appsparameters.pages.app_update": "アプリを{{$1}}更新します(アプリは{{$2}}回使用されます)。", + "scenes.app.popup.appsparameters.pages.application_title": "応用", + "scenes.app.popup.appsparameters.pages.apps_title": "アプリケーションとコネクタ", + "scenes.app.popup.appsparameters.pages.automatique_label": "自動", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "「自動」を有効にすると、このアプリケーションはこの会社の次のワークスペースに自動的に追加されます。", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "アプリケーションの公開は現在、Twakeチームによる検証を待っています。", + "scenes.app.popup.appsparameters.pages.button_force": "会社全体の力", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "タイプ '{{$1}}'およびID '{{$2}}'のイベントとパッシブ '{{$3}}'", + "scenes.app.popup.appsparameters.pages.company_label": "会社のオーナー", + "scenes.app.popup.appsparameters.pages.configuration_label": "構成", + "scenes.app.popup.appsparameters.pages.create_app_button": "アプリケーションを作成する", + "scenes.app.popup.appsparameters.pages.create_my_app": "アプリケーションを作成する", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "まだアプリを作成していません。アプリケーションまたはコネクタを作成する前に、それらがアプリケーション市場にまだ存在していないことを確認してください。", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "アプリケーションを削除する", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "危険地帯", + "scenes.app.popup.appsparameters.pages.description_label": "説明", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "会社が開発したアプリケーション", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "アプリケーションを表示する場所を定義できます。", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "ディスプレイの設定", + "scenes.app.popup.appsparameters.pages.error_check_needed": "エラーが発生しました;あなたの情報を確認してください。", + "scenes.app.popup.appsparameters.pages.error_message": "この名前はすでに別のアプリケーションで使用されています。別のものを選択してください。", + "scenes.app.popup.appsparameters.pages.error_user_code": "エラー", + "scenes.app.popup.appsparameters.pages.event_subtitle": "イベント", + "scenes.app.popup.appsparameters.pages.go_back": "戻る", + "scenes.app.popup.appsparameters.pages.publication_description": "アプリケーションの可視性を判断します。", + "scenes.app.popup.appsparameters.pages.publication_label": "出版物", + "scenes.app.popup.appsparameters.pages.publish_app_label": "アプリケーションを公開する", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "読み取り権限", + "scenes.app.popup.appsparameters.pages.remove_app": "アプリケーション{{$1}}を完全に削除します。", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "会社全体から削除する", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "ワークスペースから削除", + "scenes.app.popup.appsparameters.pages.status_tilte": "州", + "scenes.app.popup.appsparameters.pages.string_information": "この文字列はアプリケーションを識別し、メッセージコマンドで使用されます。", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecodeテスター", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "イベントレセプションのURL", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "待っています...", + "scenes.app.popup.appsparameters.pages.website_label": "Webサイト", + "scenes.app.popup.userparameter.pages.notif_content_label": "通知の内容", + "scenes.app.mainview.quick_search_placeholder": "クイック検索", + "scenes.app.popup.workspaceparameter.admin_current_status": "あなたは管理者です。", + "scenes.app.popup.workspaceparameter.manager_current_status": "あなたは会社の管理者です。", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "ワークスペースを削除する", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "ワークスペースを削除するには、ワークスペースに一人でいる必要があります。共同編集者を削除して、再試行してください。", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "このワークスペースを削除することを確認するには、以下に名前を入力して[削除]をクリックしてください。", + "scenes.app.popup.workspaceparameter.pages.enter": "入力 ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "アプリケーションとコネクタにアクセスする", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "ワークスペースモデレーター", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "あなたが最後の管理者であるため、ワークスペースを離れることはできません。新しい管理者を定義するか、このワークスペースを削除/アーカイブできます。", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "すべてのアプリケーション", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "あなたの会社のアプリケーション", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "アプリケーションの検索", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "このワークスペースのアプリケーション", + "scenes.app.popup.workspaceparameter.pages.install_button": "インストール", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "このワークスペースにアプリケーションをインストールします。", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "このワークスペースにインストールされているアプリケーション{{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "会社の他の領域にインストールされているアプリケーション{{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "インストールされているアプリケーション", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "次のユーザーを招待しているときにエラーが発生しました。 ", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "このワークスペースの画像を編集します", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "このワークスペースにはアプリケーションがありません", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "このワークスペースを離れる", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "読み取りアクセス", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "会社全体から削除する", + "scenes.app.popup.workspaceparameter.pages.research_by": "名前とカテゴリでアプリケーションを検索する", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "アプリケーションの検索...", + "scenes.app.popup.workspaceparameter.pages.show_button": "画面", + "scenes.app.popup.workspaceparameter.pages.title": "ワークスペース設定", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Webhookへのアクセス", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "最大サイズは5MBです。", + "scenes.apps.calendar.connectors_search_menu": "コネクタを検索...", + "scenes.apps.calendar.create_calendar_title": "カレンダーを作成する", + "scenes.apps.calendar.day_option": "日", + "scenes.apps.calendar.edit_calendar_title": "カレンダーを編集する", + "scenes.apps.calendar.export_title": "書き出す", + "scenes.apps.calendar.export_view_menu": "ビューをエクスポート...", + "scenes.apps.calendar.ics_download_menu": "ICSファイルをダウンロードする", + "scenes.apps.calendar.ics_subscription_menu": "ICSサブスクリプションリンクを取得する", + "scenes.apps.calendar.modals.advanced_options": "高度なオプション", + "scenes.apps.calendar.modals.description_placeholder": "説明", + "scenes.apps.calendar.modals.details_title": "詳細", + "scenes.apps.calendar.modals.event_adresse_placeholder": "住所", + "scenes.apps.calendar.modals.event_title_placeholder": "題名", + "scenes.apps.calendar.modals.modify_event_button": "イベントの編集", + "scenes.apps.calendar.modals.part.participants": "参加者", + "scenes.apps.calendar.modals.participants_event": "参加者", + "scenes.apps.calendar.modals.reminders": "リマインダー", + "scenes.apps.calendar.modals.remove_button": "消去", + "scenes.apps.calendar.modals.remove_event_button": "イベントを削除", + "scenes.apps.calendar.modals.remove_event_text": "イベントを削除しますか?", + "scenes.apps.calendar.modals.title_placeholder": "題名", + "scenes.apps.calendar.modify_calendar_menu": "カレンダーを編集する", + "scenes.apps.calendar.month_option": "月", + "scenes.apps.calendar.my_calendar": "私のカレンダー", + "scenes.apps.calendar.my_calendar_label": "私のカレンダー", + "scenes.apps.calendar.my_calendar_menu": "私のカレンダー", + "scenes.apps.calendar.today_menu": "今日", + "scenes.apps.calendar.week_option": "週", + "scenes.apps.calendar.workspace": "ワークスペース", + "scenes.apps.calendar.workspace_menu": "ワークスペース", + "scenes.apps.drive.add_button": "追加", + "scenes.apps.drive.message_added_file": "{{$1}}は{{$2}}を送信しました。", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}}は複数のファイルを送信しました。", + "scenes.apps.drive.message_added_file_no_name": "{{$1}}はファイルを送信しました。", + "scenes.apps.drive.choose_folder_button": "ディレクトリを選択してください", + "scenes.apps.drive.choose_file_button": "ファイルを選択", + "scenes.apps.drive.create_folder_button": "作成", + "scenes.apps.drive.download_button": "ダウンロード", + "scenes.apps.drive.open_link": "新しいウィンドウでリンクを開く", + "scenes.apps.drive.files_subtitle": "ファイル", + "scenes.apps.drive.folder_subtitle": "フォルダー", + "scenes.apps.drive.import_from_computer_menu": "コンピュータからアップロード", + "scenes.apps.drive.move_text": "動く", + "scenes.apps.drive.viewer.no_preview_message": "この種のファイルは表示できません。", + "scenes.apps.drive.viewer.open_with_button": "で開く...", + "scenes.apps.messages.input.placeholder": "メッセージを書く。 @を使用してユーザーを引用します。", + "scenes.apps.messages.input.edited": "編集済み", + "scenes.apps.messages.just_you": "あなただけに見える", + "scenes.apps.messages.message.remove_button": "消去", + "scenes.apps.messages.message.reply_button": "返事", + "scenes.apps.messages.message.save_button": "保存する", + "scenes.apps.messages.message.show_responses_button": "すべての回答を表示", + "scenes.apps.messages.message.types.first_channel_message_text": "これはチャンネルの最初のメッセージです", + "scenes.apps.messages.message.types.first_message_text": "これが最初のメッセージです", + "scenes.apps.messages.messageslist.get_writing_user": "書いています...", + "scenes.apps.messages.messageslist.go_last_message_button": "最後のメッセージに移動", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "新しいメッセージ", + "scenes.error_on_twake": "「ヒューストン、私たちは問題を抱えています」", + "scenes.help_us": "ただし、このエラーの修正を支援したい場合は、以下のメッセージを送信してください。 ", + "scenes.login.verifymail.alert": "私たちはあなたの電子メールをチェックしています!", + "scenes.login.verifymail.error_message": "エラーが発生しました", + "scenes.login.verifymail.signin_button": "ログイン", + "scenes.login.verifymail.success": "あなたの電子メールは正常に確認されました!", + "scenes.login.verifymail.verification_waiting": "確認を待っています...", + "scenes.apps.messages.new_thread": "新しいディスカッションを開始します", + "scenes.apps.messages.input.send_message": "メッセージを送る", + "scenes.apps.messages.input.emoji": "絵文字", + "scenes.apps.messages.input.hide_formatting": "フォーマットを非表示", + "scenes.apps.messages.input.show_formatting": "フォーマットを表示", + "scenes.tell_us": "あなたが何をしていたか教えてください:", + "scenes.apps.drive.viewer.download_desktop": "アプリでプレビューするには、Twakeデスクトップをダウンロードしてください", + "scenes.apps.tasks.my_tasks": "私のタスク", + "scenes.apps.tasks.board.place_holder": "ボード名", + "scenes.apps.tasks.board.tasks.subtask": "サブタスク", + "scenes.apps.tasks.board.tasks.add_subtask": "サブタスクを追加する", + "scenes.apps.tasks.board.tasks.use_deadline": "期限を使用する", + "scenes.apps.tasks.board.tasks.use_starttime": "開始時間を使用する", + "scenes.apps.tasks.board.starts": "を開始します", + "scenes.apps.tasks.board.ends": "のために行われる", + "scenes.app.popup.sync_calendar": "カレンダーを同期します。", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "会社のロゴ", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "会社の画像を編集する ", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "招待をキャンセルする", + "scenes.apps.account.account.fullname": "フルネーム", + "scenes.apps.account.account.password_for_user": "ユーザーのパスワード", + "scenes.apps.account.account.send_info": "この資格情報をユーザーに送信します。", + "scenes.apps.account.message_temporary": "一時アカウントは通常のTwakeアカウントと同じように機能しますが、パスワードを作成すると、必要に応じてパスワードをリセットできます。", + "scenes.apps.account.message_user_signin": "ユーザーは、この同じ電子メールを使用していつでもサインインし、一時アカウントを通常のアカウントに変更できます。", + "scenes.app.mainview.link_expired": "このパブリックリンクは無効であるか、有効期限が切れています。", + "scenes.app.mainview.create_account": "で無料でワークスペースを作成する ", + "scenes.apps.calendar.modals.reminder_add": "リマインダーを追加する", + "scenes.apps.parameters.workspace_sections.members.invite_all": "すべてを招待する", + "scenes.app.taskpicker.select": "選択する", + "components.listmanager.filter": "フィルター", + "scenes.apps.tasks.no_connector": "コネクタなし", + "components.attachmentpicker.add_attachment": "添付ファイルを追加する", + "components.input.copied": "コピー", + "components.drive.new_versions": "新しいバージョンを追加する", + "components.drive.navigators.directory_not_found": "ディレクトリが見つかりません。", + "components.drive.right_preview.suppress_link": "リンクを抑制します", + "components.drive.right_preview.create_link": "アクセスリンクを作成する", + "components.drive.moove_here": "ここに移動", + "components.drive.modify_uslist": "ユーザーリストを変更する", + "components.tagpicker.tag_name": "タグ名", + "components.upload.drop_files": "ここにファイルをドロップします", + "components.workspace.list_manager.no_workspace": "ワークスペースなし", + "components.workspace.list_manager.add": "ワークスペースを追加する", + "components.workspace.list_manager.current_space": "現在のワークスペース", + "components.workspace.list_manager.current_company": "現在の会社", + "components.workspace.calendar.invalid": "無効", + "components.searchpopup.enter_text": "Twakeを検索するためのテキストを入力します。", + "components.searchpopup.loading": "より多くの結果をロードする", + "components.searchpopup.filter_ws": "ワークスペースをフィルタリングする", + "components.searchpopup.creation": "創造", + "components.searchpopup.update_search": "検索を更新", + "components.searchpopup.last_modif": "最終変更", + "components.searchpopup.sender": "送信者", + "components.searchpopup.mentions": "言及", + "components.searchpopup.only_pinned": "固定されたメッセージのみ", + "components.alert.confirm": "アクションを確認する", + "components.alert.confirm_click": "[OK]をクリックしてアクションを確認します。", + "components.searchpopup.tasks": "タスク", + "scenes.apps.board.archived_tasks": "アーカイブされたタスク({{$1}})", + "scenes.apps.board.active_tasks": "アクティブなタスク", + "scenes.apps.board.kanban": "かんばん", + "scenes.apps.board.display_as": "表示", + "scenes.apps.board.new_task": "+新しいタスク", + "scenes.apps.board.all_boards": "すべてのボード", + "components.userlistmanager.no_users": "ユーザーはいません。", + "scenes.apps.drive.used": "このフォルダで使用されます", + "components.reminder.notification": "通知", + "components.reminder.minutes_bef": "数分前", + "components.reminder.hours_bef": "数時間前", + "components.reminder.days_bef": "前日", + "components.reminder.weeks_bef": "数週間前", + "components.reminder.by_email": "Eメール", + "scenes.apps.calendar.reminders": "リマインダー", + "scenes.app.mainview.discussion": "議論", + "components.tagpicker.notag": "タグなし", + "scenes.apps.tasks.modals.attachments": "添付ファイル", + "components.calendar.calendarselector.from": "から", + "scenes.apps.drive.move_text2": "動く", + "components.attachmentpicker.from_computer": "お使いのデバイスから", + "components.attachmentpicker.from_twake": "Twakeドキュメントから", + "components.attachmentpicker.file": "ファイル", + "components.attachmentpicker.remove_attach": "添付ファイルを削除します", + "scenes.apps.drive.remove_attachs": "添付ファイルを削除します", + "components.drive.elements.see": "見る", + "components.drive.elements.current_name": "現在の名前: ", + "components.drive.elements.configurate_mod": "modを設定します...", + "components.drive.elements.manage_version": "バージョンを管理する", + "scenes.app.popup.createcompany.try_again": "もう一度やり直してください。", + "scenes.app.popup.workspace.edit_temp": "一時的なアカウントを編集する", + "scenes.app.popup.workspace.create_temp": "一時的なアカウントを作成する", + "scenes.apps.tasks.active_tasks": "アクティブなタスク", + "scenes.apps.drive.right_preview.versions": "バージョン", + "scenes.app.popup.appsparameters.pages.title_informations": "基本情報", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "アプリケーション管理に関する情報", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "現在のユーザーID", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "現在のワークスペースID", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "現在のグループID", + "scenes.app.mainview.channel_description": "チャネルについて説明する", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "すべてのワークスペースユーザーをこのチャネルに自動的に招待します", + "scenes.client.channelbar.channelmemberslist.title": "{{$1}}のユーザー", + "scenes.client.channelbar.channelmemberslist.loader": "もっと読み込む", + "scenes.client.channelbar.channelmemberslist.autocomplete": "ユーザーを追加または検索する", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "チャネルから削除", + "components.leftbar.channel.workspaceschannels.menu.option_1": "チャネルを作成する", + "components.leftbar.channel.workspaceschannels.menu.option_2": "チャンネルに参加する", + "components.channelworkspacelist.title": "チャンネル", + "scenes.client.channelbar.workspacechannellist.autocomplete": "チャネル、ユーザー、またはダイレクトメッセージを検索する", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "新しいタブを作成する", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "名前を変更{{$1}}", + "components.connectorslistmanager.add_connectors": "コネクタを追加します", + "components.notifications.hidden_notifications_button.children": "新しいメッセージ", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "応用", + "scenes.client.channelbar.channelmemberslist.no_members": "このチャネルにはユーザーがいません。[ユーザーの追加]をクリックして招待できます。", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "ディスカッションを非表示", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}}メールが追加されます", + "components.newversion.new_version_component.row.part_1": "古いバージョンのTwakeを実行しています", + "components.newversion.new_version_component.row.part_2": "アプリをリロードして、新機能をお楽しみください。", + "components.newversion.new_version_component.link": "リロードするには、ここをクリックしてください", + "components.newversion.new_version_modal.title": "新しいアップデートが利用可能です!", + "scenes.apps.drive.download_all_button": "すべてダウンロード", + "components.inputs.input_with_select.input.placeholder": "チャンネル名", + "components.inputs.input_with_select.select.placeholder": "セクション名", + "components.inputs.input_with_select.select.no_sections": "最初のチャンネルセクションの名前を書き始めます。", + "components.inputs.input_with_select.button.tooltip": "チャネルセクションを設定する", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}}が{{$2}}をチャンネルに追加しました", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}}説明を変更しました", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}}はチャネルの名前を{{$2}}に変更しました", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}}は新しい{{$2}}タブを追加しました{{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}}は{{$2}}タブ{{$3}}を削除しました", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}}は新しいコネクタを追加しました{{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}}コネクタを取り外しました{{$2}}", + "scenes.client.channelbar.channelmemberslist.tag": "君は", + "components.alert.leave_private_channel.title": "チャンネルを離れてもよろしいですか?", + "components.alert.leave_private_channel.description": "誰かがあなたを招待しない限り、このプライベートチャンネルに再び参加することはできません。", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "あなたは会員ではありません", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "もっと読み込む", + "general.re_send": "再送信", + "general.verify": "確認", + "components.unverified_account.typography_text_danger": "試用期間の残り日数は{{$1}}です。トライアルアカウントは7日後にブロックされ、登録から1か月後に完全に削除されます。送信された確認メールの[アカウントを確認]ボタンをクリックすると、アカウントを確認できます。", + "components.unverified_account.verification_details": "確認の詳細をに送信しました", + "components.account_verication_status_unverified": "未確認", + "components.account_verication_status_blocked": "ロック済み", + "components.unverified_account.re_send_email": "メールが届きませんでしたか?", + "components.blocked_account.trial_period_over": "試用期間が終了しました。アカウントのロックを解除してすべての機能にアクセスするには、確認メールでアカウントを確認してください", + "components.add_mails_workspace.button": "Twakeの使用を開始します", + "services.console_services.toaster.success_verify_email": "確認リンクがメールアカウントに送信されました", + "scenes.app.popup.workspaceparameter.edit_from_console": "コンソールで見る", + "services.console_services.toaster.success_invite_emails": "{{$1}}ユーザーが正常に追加されました", + "scenes.client.channels_bar.modals.guest_management.title": "{{$1}}でゲストを管理する", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "ゲストまたは保留中のメールを検索", + "scenes.client.channels_bar.modals.guest_management.tips": "上記の入力を使用して、メールの追加または検索を開始します", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "メールが送信されました", + "general.user.role.company.admin": "会社の管理者", + "general.user.role.company.guest": "ゲスト", + "general.user.deleted": "削除されたアカウント", + "components.richtexteditor.toolbar.bold": "大胆な", + "components.richtexteditor.toolbar.underline": "下線を引く", + "components.richtexteditor.toolbar.italic": "イタリック", + "components.richtexteditor.toolbar.strikethrough": "取り消し線", + "components.richtexteditor.toolbar.code": "コード", + "components.richtexteditor.toolbar.unordered-list": "箇条書き", + "components.richtexteditor.toolbar.ordered-list": "注文リスト", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "ここをクリック", + "components.emoji_picker.categories.travel_and_places": "旅行と場所", + "components.emoji_picker.categories.objects": "オブジェクト", + "components.emoji_picker.categories.symbols": "記号", + "components.emoji_picker.categories.flags": "フラグ", + "components.emoji_picker.categories.search_result": "の検索結果", + "components.emoji_picker.categories.not_found": "絵文字が見つかりません", + "'": "'", + "\"": "「」", + "login.create_account": "アカウントを作成する", + "scenes.apps.messages.message.types.no_message_in_thread": "まだ誰も返事をしなかった。", + "login.login_error": "ログイン中のエラー", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "まだ誰もあなたをワークスペースに招待していません。", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "デフォルトのワークスペース", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "すべてのワークスペースユーザーをこのチャネルに自動的に招待します", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "{{$1}}を削除しようとしています", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "{{$2}}にはまだ{{$1}}メンバーがいます。このワークスペースを削除できるようにするには、すべてのメンバーを削除する必要があります。", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "ワークスペースのメッセージとファイルがすべて削除されることを理解しています。", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "ロゴの最大サイズは5MBです", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "形式が正しくありません。pnggifとjpgのみが許可されます", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "不明なエラー", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "エラー", + "scenes.app.channelsbar.currentuser.reset": "リセット", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "ユーザーを表示するために少なくとも3文字を書く", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "ユーザーが見つかりません", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "絵文字が見つかりません", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "コマンドが見つかりません", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}}が書いています...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}}と{{$2}}が書いています...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}、{{$2}}、{{$3}}より多くのユーザーが書いています...", + "components.locked_features_components.locked_invite_alert.message_part_1": "あなたの会社は{{$1}}メンバーの上限に達しました。お願いします ", + "components.locked_features_components.locked_invite_alert.message_link": "あなたの会社をアップグレードする", + "components.locked_features_components.locked_invite_alert.message_part_2": " より多くのメンバーを招待します。", + "components.locked_features_components.locked_invite_alert.message_magic_link": " 会社の所有者または管理者に連絡してください。", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "コンソールですべての会社のメンバーを見る", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "アプリケーションを簡単に説明してください", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "この会社の所有者と管理者がこのアプリケーションを変更して公開できることを理解しています。", + "scenes.app.popup.appsparameters.pages.application_creator.title": "新しい統合", + "twake.application.access.title": "アプリケーションに適したスコープを選択してください。", + "twake.application.access.no_default_scopes_available'": "この統合には{{$1}}アクセスはありません", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "TwakeAPIドキュメント", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "これらを埋める方法がわからない場合は、 ", + "scenes.app.popup.appsparameters.pages.app.private_key": "秘密鍵", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "アプリケーション{{$1}}が正常に削除されました!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "アプリケーションの削除中にエラーが発生しました{{$1}}!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "{{$1}}アプリケーションに成功しました!", + "scenes.app.integrations_parameters.add_application": "新しい統合", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "開発者設定", + "components.rich_text_editor.plugins.suggestions.loading": "もっとお探しですか", + "components.open_desktop_popup.subtitle": "Twakeアプリで開きました", + "components.open_desktop_popup.open_here_link": "代わりにここを開く", + "molecules.download_banner.title": "Twakeを最大限に活用し、今すぐデスクトップアプリをダウンロードしてください", + "molecules.download_banner.download_button": "デスクトップアプリをダウンロード", + "scenes.app.channelsbar.channel_copy_link": "チャネルリンクをコピーする", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "正常に更新されました", + "components.searchpopup.no_results_for": "の結果はありませんでした", + "components.searchpopup.try_new_search": "新しい検索をお試しください", + "components.searchpopup.all": "全て", + "components.searchpopup.chats": "チャット", + "components.searchpopup.media": "メディア", + "components.searchpopup.files": "ファイル", + "components.searchpopup.recent_chats": "最近のチャット", + "components.searchpopup.recent_media": "最近のメディア", + "components.searchpopup.recent_files": "最近使用したファイル", + "components.searchpopup.recent_channels_and_contacts": "最近のチャンネルと連絡先", + "components.searchpopup.header_title": "探す", + "components.searchpopup.scope.company": "すべての会社で", + "components.searchpopup.scope.channel": "このチャンネルで", + "components.searchpopup.channels": "チャネル", + "components.searchpopup.messages": "メッセージ" +} diff --git a/twake/frontend/public/locales/nb_NO.json b/twake/frontend/public/locales/nb_NO.json index 20017c2596..90cd970d57 100644 --- a/twake/frontend/public/locales/nb_NO.json +++ b/twake/frontend/public/locales/nb_NO.json @@ -91,5 +91,820 @@ "scenes.apps.calendar.event_edition.checkbox_all_day": "Hele dagen", "scenes.apps.calendar.calendar.week_btn": "Uke", "scenes.apps.drive.navigators.new_file.untitled": "Uten navn", - "scenes.apps.drive.right_preview.public_link": "Offentlig lenke" -} \ No newline at end of file + "scenes.apps.drive.right_preview.public_link": "Offentlig lenke", + "scenes.app.popup.appsparameters.pages.remove_app_button": "Slett søknad", + "scenes.apps.calendar.modals.details_title": "Detaljer", + "scenes.apps.board.new_task": "+ Ny oppgave", + "scenes.app.popup.workspace.edit_temp": "Rediger midlertidig konto", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} e-post(er) vil bli lagt til", + "components.newversion.new_version_component.row.part_1": "Du kjører en utdatert Twake-versjon", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} ga nytt navn til kanalen til {{$2}}", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} la til en ny {{$2}}-fane {{$3}}", + "scenes.client.channelbar.channelmemberslist.tag": "Du", + "scenes.app.integrations_parameters.title": "Integrasjoner", + "scenes.app.integrations_parameters.applications_table.name": "Navn", + "scenes.app.integrations_parameters.applications_table.title": "Andre integrasjoner", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Søkeapplikasjon", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Nettsted", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Opprettelsesdato", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Versjon", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Forestilling", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Fjern fra selskapet", + "scenes.apps.messages.input.replied_to": "svarte på ", + "scenes.join.login_first_button": "Logg inn eller opprett en konto først", + "scenes.join.join_the_team_button": "Bli med på laget", + "scenes.app.popup.appsparameters.pages.website_label": "Nettsted", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Skriveprivilegier", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Du kan ikke slette denne appen hvis den er publisert.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Det oppstod en feil under oppdatering av applikasjonen.", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Søk i applikasjoner", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Applikasjoner av dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Gå tilbake til søket", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Inviter brukere", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Brukere", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Applikasjoner utviklet av selskapet", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Identiteten til selskapet", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Integrasjoner", + "scenes.apps.calendar.day_option": "Dag", + "scenes.apps.calendar.modals.modify_event_button": "Rediger hendelse", + "scenes.apps.calendar.modals.part.participants": "Deltakere", + "scenes.apps.drive.throw_menu": "Send til søpla", + "scenes.apps.drive.trash_empty_menu": "Tøm søpla", + "scenes.help_us": "Men hvis du ønsker å hjelpe oss med å fikse denne feilen, send oss en melding nedenfor: ", + "scenes.login.verifymail.alert": "Vi sjekker e-posten din!", + "scenes.login.verifymail.error_message": "En feil oppstod", + "scenes.apps.calendar.unconfigured_tab": "Denne fanen er ikke konfigurert ennå.", + "scenes.apps.drive.trash": "Søppel", + "scenes.apps.drive.top_menu_more": "Mer", + "scenes.apps.drive.top_menu_no_items": "{{$1}} elementer", + "scenes.apps.messages.new_thread": "Start en ny diskusjon", + "scenes.apps.messages.input.send_message": "Sende melding", + "scenes.apps.messages.input.emoji": "Emoji", + "scenes.apps.messages.input.hide_formatting": "Skjul formatering", + "scenes.apps.messages.input.show_formatting": "Vis formatering", + "scenes.tell_us": "Fortell oss hva du gjorde på:", + "scenes.apps.drive.viewer.download_desktop": "Last ned Twake Desktop for å forhåndsvise i appen", + "scenes.apps.tasks.my_tasks": "Mine oppgaver", + "scenes.apps.tasks.board.place_holder": "Styrenavn", + "scenes.apps.tasks.board.tasks.subtask": "Deloppgave", + "scenes.apps.tasks.board.tasks.add_subtask": "Legg til en deloppgave", + "scenes.apps.tasks.board.tasks.use_deadline": "Bruk frist", + "scenes.apps.parameters.workspace_sections.members.invite_all": "Inviter alle", + "scenes.app.taskpicker.select": "Plukke ut", + "components.listmanager.filter": "Filter", + "scenes.apps.tasks.no_connector": "Ingen kontakt", + "scenes.apps.drive.used": "brukt i denne mappen", + "components.reminder.notification": "Melding", + "components.reminder.minutes_bef": "minutter før", + "components.reminder.hours_bef": "timer før", + "components.reminder.days_bef": "dager før", + "components.reminder.weeks_bef": "uker før", + "components.reminder.by_email": "E-post", + "components.alert.leave_private_channel.title": "Er du sikker på at du vil forlate kanalen?", + "components.alert.leave_private_channel.description": "Du vil ikke kunne bli med i denne private kanalen igjen med mindre noen inviterer deg.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Du er ikke medlem", + "components.emoji_picker.categories.frequently_used": "Ofte brukt", + "components.emoji_picker.categories.smileys_and_people": "Smileys og mennesker", + "components.emoji_picker.categories.animals_and_nature": "Dyr og natur", + "components.emoji_picker.categories.food_and_drink": "Mat drikke", + "components.emoji_picker.categories.activity": "Aktivitet", + "components.emoji_picker.categories.travel_and_places": "Reise og steder", + "components.emoji_picker.categories.objects": "Objekter", + "components.emoji_picker.categories.symbols": "Symboler", + "components.emoji_picker.categories.flags": "Flagg", + "components.emoji_picker.categories.search_result": "Søkeresultater", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Legg til i favoritter", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Fjern fra favoritter", + "scenes.apps.messages.left_bar.stream.notifications": "Varsler...", + "scenes.apps.messages.left_bar.stream.notifications.all": "Enhver melding", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} og {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "Bare {{$1}}", + "scenes.apps.messages.left_bar.stream.notifications.never": "Ingenting", + "scenes.apps.parameters.workspace_sections.workspace": "Arbeidsområde", + "scenes.apps.parameters.workspace_sections.members": "Deltakere", + "scenes.apps.parameters.group_sections.workspaces": "Arbeidsområder", + "scenes.apps.parameters.group_sections.apps": "Apper", + "scenes.apps.account.title": "Kontoparametere", + "scenes.apps.account.languages.menu_title": "Språk", + "scenes.apps.account.account.firstname": "Fornavn", + "scenes.apps.account.account.lastname": "Etternavn", + "scenes.apps.account.account.username": "Brukernavn", + "scenes.apps.account.account.change_username": "Endre ditt unike brukernavn.", + "scenes.apps.account.account.emails": "E-poster", + "scenes.apps.account.account.main_email": "Hoved e-post", + "scenes.apps.account.account.email_add": "Legg til ny e-post", + "scenes.apps.account.account.email_add_modal.invalid_code": "Denne koden er ugyldig", + "scenes.apps.account.account.password": "Passord", + "scenes.apps.account.account.password_modal.old_password": "Nåværende passord", + "scenes.apps.account.account.password_modal.password": "Nytt passord", + "scenes.apps.account.account.password_modal.bad_old_password": "Gammelt passord er ikke riktig.", + "scenes.apps.account.account.password_modal.bad_password": "Passordene dine stemmer ikke overens, eller de er for korte. Vennligst skriv inn et passord med minst 8 tegn.", + "scenes.apps.account.account.logout": "Logg ut", + "scenes.apps.account.languages.text": "Endre Twake-språket.", + "scenes.apps.account.notifications.title": "Varsler", + "scenes.apps.account.notifications.keywords_subtitle": "Nøkkelord", + "scenes.apps.account.notifications.keywords_placeholder": "dev, wifi, kode, ...", + "scenes.apps.account.notifications.disturb_option_a": "Ikke send meg push-varsler mellom ", + "scenes.apps.account.notifications.disturb_option_b": " og ", + "scenes.apps.account.notifications.disturb_option_c": " (lokal tidssone)", + "scenes.apps.account.notifications.devices_subtitle": "Enhetsvarsler", + "scenes.apps.account.notifications.devices_option_ever": "Send meg alltid push-varsler", + "scenes.apps.account.notifications.devices_option_inactive": "Send meg push-varsler når jeg er inaktiv på skrivebordet", + "scenes.apps.account.notifications.devices_option_never": "Send meg aldri push-varsler", + "scenes.apps.account.notifications.privacy_subtitle": "Personvern", + "scenes.apps.account.notifications.mail_subtitle": "E-postvarsler", + "scenes.apps.account.notifications.sound": "Lydvarsling", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Utvidelse", + "scenes.apps.parameters.workspace_sections.members.members": "Brukere", + "scenes.apps.parameters.workspace_sections.members.pending": "Ventende e-poster", + "scenes.apps.parameters.workspace_sections.members.invite": "Inviter ny bruker", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "Legg til bruker", + "scenes.apps.tasks.connectors_menu": "Koblinger...", + "scenes.apps.tasks.connectors_search_menu": "Søk etter koblinger...", + "scenes.apps.tasks.no_connectors_menu_text": "Du har ingen koblinger som kan kobles til en kalender.", + "scenes.apps.tasks.unconfigured_tab": "Denne fanen er ikke konfigurert ennå.", + "scenes.apps.tasks.choose_board_button": "Velg et brett", + "scenes.apps.tasks.new_board.title": "Nytt styre", + "scenes.apps.tasks.new_board.edit_title": "Rediger tavle", + "scenes.apps.tasks.task": "Oppgave", + "scenes.apps.tasks.no_tasks": "Ikke spør", + "scenes.apps.tasks.task_status.todo": "Å gjøre", + "scenes.apps.tasks.task_status.current": "Strøm", + "scenes.apps.tasks.task_status.done": "Ferdig", + "scenes.apps.tasks.task.description": "Beskrivelse", + "scenes.apps.tasks.task.assignees": "Oppdragstakere", + "scenes.apps.tasks.task.edit.dates": "Datoer", + "scenes.apps.tasks.list_modal.modify_list": "Endre listen", + "scenes.apps.tasks.list_modal.new_list": "Ny liste", + "scenes.apps.tasks.list_modal.remove": "Fjern liste og oppgaver", + "scenes.apps.tasks.list_modal.predefined_participants": "Forhåndsdefinerte deltakere", + "scenes.apps.tasks.list_modal.archive_all_tasks": "Arkiver alle oppgaver", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Fjern arkiverte oppgaver ({{$1}})", + "scenes.login.footer.go_to_twake": "Gå til twakeapp.com", + "scenes.login.footer.branding": "Du er på en {{$1}} ({{$2}}) privat Twake-server. ", + "scenes.login.create_account.title": "Lag en ny bruker", + "scenes.login.create_account.email": "E-post", + "scenes.login.create_account.email_used": "Denne e-posten er allerede i bruk.", + "scenes.login.create_account.username": "Brukernavn", + "scenes.login.create_account.username_already_exist": "dette brukernavnet er allerede i bruk", + "scenes.login.create_account.fill_in_username": "Du må fylle inn brukernavnet ditt", + "scenes.login.create_account.fill_in_email": "Du må fylle ut e-posten din med riktig e-post", + "scenes.login.create_account.too_short_password": "Passordet ditt må inneholde minst 8 tegn.", + "scenes.login.create_account.firstname": "Fornavn", + "scenes.login.create_account.newsletter": "Motta informasjon om Twake", + "scenes.login.create_account.lastname": "Etternavn", + "scenes.login.forgot_password.title": "Glemt passord?", + "scenes.login.forgot_password.text": "Du vil motta en 9-sifret kode på e-post for å bekrefte identiteten din.", + "scenes.login.forgot_password.email_to_recover": "E-post for å gjenopprette", + "scenes.login.forgot_password.mail_doesnt_exist": "Denne e-posten eksisterer ikke", + "scenes.login.forgot_password.text2": "Du vil motta en 9-sifret kode. Vennligst skriv det inn i feltet under for å fortsette.", + "scenes.login.forgot_password.invalid_code": "Denne koden er ikke gyldig.", + "scenes.login.forgot_password.text3": "Skriv inn et nytt passord for kontoen din.", + "scenes.login.forgot_password.password": "Passord", + "scenes.login.forgot_password.password2": "Bekreft passord", + "scenes.login.forgot_password.password_dont_match": "Passordene dine stemmer ikke overens, eller de er for korte. Vennligst skriv inn et passord med minst 8 tegn.", + "scenes.login.home.title": "Logg på Twake", + "scenes.login.home.subtitle": "Glad for å se deg", + "scenes.login.home.email": "E-post", + "scenes.login.home.unable_to_connect": "Ugyldige legitimasjon", + "scenes.login.home.password": "Passord", + "scenes.login.home.login_btn": "Logg Inn", + "scenes.login.home.lost_password": "Glemt passord?", + "scenes.login.home.create_account": "Opprett en konto", + "scenes.login.create_account.password": "Passord", + "scenes.login.create_account.step_1_subtitle": "Det kunne ikke vært enklere – vi trenger bare litt informasjon.", + "scenes.login.create_account.step_2_subtitle_a": "Legg til hele navnet ditt slik at andre brukere kan gjenkjenne deg.", + "scenes.login.create_account.step_2_subtitle_b": "Telefonnummeret ditt forblir privat.", + "scenes.login.create_account.step_3_mail_sent": "Vi har sendt deg en aktiveringslenke på e-post.", + "scenes.login.create_account.step_3_subtitle": "Siste trinn – vi må bekrefte at du ikke er en robot!", + "scenes.app.workspaces.create_company.company_name.placeholder": "Selskapsnavn", + "scenes.app.workspaces.create_company.company_name.title_1": "Å begynne,", + "scenes.app.workspaces.create_company.company_name.title_2": "angi navnet på bedriften din.", + "scenes.app.workspaces.create_company.default_workspace_name": "Hoved", + "scenes.app.workspaces.create_company.importations.title_1": "Jobber du allerede med digitale verktøy? Importer eller integrer verktøyene dine nå!", + "scenes.app.workspaces.create_company.importations.title_2": "Ingen grunn til bekymring, du kan gjøre dette senere!", + "scenes.app.workspaces.create_company.invitations.title_2": "Legg til brukere i teamet ditt.", + "scenes.app.workspaces.create_company.title": "Opprett firmaet mitt", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "Legg til en sekundær e-post", + "scenes.app.workspaces.welcome_page.added_to_company": "Du er invitert til ", + "scenes.app.workspaces.welcome_page.create_my_company": "Opprett firmaet mitt", + "scenes.app.workspaces.welcome_page.lets_go": "La oss gå!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Ble du invitert med en annen e-postadresse?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Å, vel... Det ser ut til at ingen har invitert deg til en arbeidsplass ennå.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Du er klar til å jobbe nå.", + "scenes.app.workspaces.welcome_page.see_you_soon": "Ser deg snart!", + "scenes.app.workspaces.welcome_page.try_again": "Prøv igjen", + "scenes.app.workspaces.welcome_page.twake_team": "Twake", + "scenes.app.workspaces.welcome_page.welcome_header": "Velkommen til Twake!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Du kan koble flere e-postadresser til kontoen din; kun én adresse vil bli brukt til å sende deg varsler.", + "scenes.app.workspaces.welcome_page.main_mail_title": "Hovedadresse", + "scenes.app.workspaces.welcome_page.other_mail_title": "Sekundære adresser", + "scenes.app.workspaces.welcome_page.add_new_email": "Legg til en e-post", + "scenes.app.workspaces.welcome_page.code_verification": "Bekreftelseskode", + "scenes.app.workspaces.welcome_page.new_email": "Legg til en sekundær e-post", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Vi sendte deg en bekreftelseskode via {{$1}}", + "scenes.app.workspaces.welcome_page.done": "jeg er ferdig", + "scenes.login.forgot_password.finished": "Passordet ditt ble oppdatert.", + "scenes.apps.account.account.description_main": "Hovedadressen din er der Twake sender varslene dine. Dine sekundære adresser lar deg automatisk inviteres til arbeidsområdene som bruker dem.", + "scenes.apps.account.account.emails.description": "Administrer de forskjellige e-postadressene dine.", + "scenes.apps.account.account.make_main": "Sett hoved", + "scenes.apps.account.account.password.description": "Bytt passord.", + "scenes.apps.account.identity": "Identitet", + "scenes.apps.account.identity.description": "Endre fornavn, etternavn og profilbilde synlig for andre Twake-brukere.", + "scenes.apps.account.preference": "Preferanser", + "scenes.apps.account.thumbnail.max_weight": "Maksimal størrelse 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "Bekreft denne e-posten", + "app.name.twake_calendar": "Kalender", + "app.name.twake_drive": "Dokumenter", + "app.name.twake_tasks": "Oppgaver", + "components.calendar.repetition.everyday": "Daglig", + "components.calendar.repetition.does_not_repeat": "Gjentas ikke", + "components.calendar.repetition.weekly_on": "Ukentlig på {{$1}}", + "components.calendar.repetition.monthly_on": "Månedlig på {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Månedlig på dag {{$1}}", + "components.calendar.repetition.annually_on": "Årlig på {{$1}}", + "components.calendar.repetition.every_weekday": "Hver ukedag (man-fre)", + "components.calendar.repetition.custom": "Tilpasset...", + "components.calendar.repetition.repeat": "Gjenta hver", + "components.calendar.repetition.ends": "Slutter", + "components.calendar.repetition.never": "Aldri", + "components.calendar.repetition.after": "Etter", + "components.calendar.repetition.days": "dager)", + "components.calendar.repetition.weeks": "uke(r)", + "components.calendar.repetition.months": "måneder)", + "components.calendar.repetition.years": "år", + "components.calendar.repetition.custom_recurrence": "Tilpasset gjentakelse", + "components.calendar.repetition.occurrence": "Forekomst(er)", + "components.calendar.repetition.repeat_on": "Gjenta på", + "scenes.app.channelsbar.currentuser.add_apps": "Søk i applikasjoner", + "scenes.app.channelsbar.currentuser.change_my_status": "Endre statusen min", + "scenes.app.channelsbar.currentuser.collaborateurs": "Brukere", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Lag et arbeidsområde", + "scenes.app.channelsbar.currentuser.invited_status": "Du er en gjest.", + "scenes.app.channelsbar.currentuser.title": "Kontoinnstillinger", + "scenes.app.channelsbar.currentuser.workspace_info": "Du er i arbeidsområdet {{$1}} fra gruppen {{$2}}", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Arbeidsområdeinnstillinger", + "scenes.app.channelsbar.currentuser.logout": "Logg ut", + "scenes.app.channelsbar.currentuser.update": "Oppdater", + "scenes.app.channelsbar.currentuser.disable_notifications": "Deaktiver", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Deaktiver i 1 time", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Deaktiver til kl. 09.00 i morgen", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Aktiver på nytt", + "scenes.app.channelsbar.currentuser.user_parameter": "Varslingsinnstillinger", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Du kan importere disse kanalene til virksomheten din for å holde deg organisert ved å klikke på denne rammen.", + "scenes.apps.drive.viewer.edit_with_button": "Rediger med {{$1}}", + "scenes.apps.drive.viewer.loading_preview_message": "Laster inn...", + "scenes.apps.drive.viewer.no_preview_message": "Kan ikke se denne typen fil.", + "scenes.apps.drive.viewer.open_with_button": "Åpne med...", + "scenes.apps.messages.input.placeholder": "Skrive en melding. Bruk @ for å sitere en bruker.", + "scenes.apps.messages.input.edited": "Redigert", + "scenes.apps.messages.just_you": "Bare synlig for deg", + "scenes.apps.messages.message.new_messages_bar": "Nye meldinger", + "scenes.apps.messages.message.cancel_button": "Avbryt", + "scenes.apps.messages.message.modify_button": "Redigere", + "scenes.apps.messages.message.pin_button": "Fest melding", + "scenes.apps.messages.message.unpin_button": "Løsne melding", + "scenes.apps.messages.message.copy_link": "Kopier lenke til melding", + "scenes.apps.messages.message.pinned": "Festet", + "scenes.apps.messages.message.remove_button": "Slett", + "scenes.apps.messages.message.reply_button": "Svare", + "scenes.apps.messages.message.save_button": "Lagre", + "scenes.apps.messages.message.show_button": "Vise", + "scenes.apps.messages.message.show_responses_button": "Se alle svarene", + "scenes.apps.messages.message.types.first_channel_message_text": "Dette er kanalens første melding", + "scenes.apps.messages.message.types.first_message_text": "Dette er den første meldingen", + "scenes.apps.messages.messageslist.get_writing_user": "skriver...", + "scenes.apps.messages.messageslist.get_writing_users": "skriver...", + "components.workspace.list_manager.all": "Alle", + "general.more": "Mer", + "scenes.apps.board.archived_tasks": "Arkiverte oppgaver ({{$1}})", + "scenes.apps.board.active_tasks": "Aktive oppgaver", + "scenes.apps.board.kanban": "Kanban", + "scenes.apps.board.display_as": "Vis som", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} fjernet {{$2}}-fanen {{$3}}", + "components.locked_features.locked_only_office_popup.text": "Huff!! Det virker som du vil redigere filen fra Twake. Det kan være lurt å vurdere å oppgradere planen din hvis du vil samarbeide rundt kontorfiler. Utforsk prisalternativene våre og velg det beste alternativet for teamsamarbeidsbehovene dine.", + "general.resume": "Gjenoppta", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Rediger bildet av dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.research_by": "Søk etter applikasjoner etter navn og kategorier", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Søk i apper...", + "scenes.app.popup.workspaceparameter.pages.show_button": "Vise", + "scenes.app.popup.workspaceparameter.pages.title": "Arbeidsområdeinnstillinger", + "scenes.apps.calendar.modals.description_placeholder": "Beskrivelse", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Invitasjonslenke til arbeidsområdet", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Ny lenke generert", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Kopiert til utklippstavlen", + "scenes.app.popup.adduser.magiclinks.action_copy": "Kopiere", + "scenes.app.popup.adduser.magiclinks.action_generate": "generere", + "scenes.app.popup.workspace.create_temp": "Opprett en midlertidig konto", + "scenes.apps.tasks.active_tasks": "aktive oppgaver", + "scenes.apps.drive.right_preview.versions": "Versjoner", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Administrer applikasjonene og koblingene dine.", + "scenes.app.popup.appsparameters.pages.icon": "Ikon", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Skjul diskusjon", + "general.pause": "Pause", + "scenes.app.integrations_parameters.company_application_popup.tag": "Installert", + "scenes.app.integrations_parameters.company_application_popup.btn": "Installere", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Informasjon", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Beskrivelse", + "scenes.app.integrations_parameters.company_applications_table.name": "Navn", + "scenes.app.integrations_parameters.company_applications_table.title": "Installert i din bedrift", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Slettet {{$1}} fra bedriften din", + "scenes.join.loading": "Laster inn …", + "scenes.join.wrong_link_title": "Denne lenken er ikke lenger tilgjengelig", + "scenes.join.wrong_link_description": "Be personen som inviterte deg til å bli med i dette selskapet om en ny lenke eller opprette ditt eget selskap", + "scenes.join.create_the_company_button": "Opprett selskapet", + "scenes.join.join_workspace_from_company": "Bli med {{$1}} fra {{$2}}!", + "scenes.join.twake_description": "Twake er et digitalt arbeidsområde med åpen kildekode bygget for å forbedre teamets produktivitet", + "general.unarchive": "Avarkiver", + "scenes.apps.calendar.event_view.article_until": "til", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Navn", + "scenes.apps.tasks.boards": "Styrer", + "general.open": "Åpen", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Gå til dokumentasjonen for å generere konfigurasjonen i JSON-format.", + "scenes.app.popup.appsparameters.pages.loading": "Laster inn...", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Passive data som vil bli sendt i neste hendelse", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "Venter...", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Logo", + "scenes.app.popup.workspaceparameter.pages.name_description": "Endre navnet på dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.name_label": "Navn på arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.no_access": "Ingen adgang.", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "Du har ingen applikasjoner i dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Forlat dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Lesetilgang", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Fjern fra hele selskapet", + "scenes.apps.calendar.modals.event_adresse_placeholder": "Adresse", + "scenes.apps.calendar.modals.event_description_placeholder": "Beskrivelse", + "scenes.apps.calendar.modals.event_title_placeholder": "Tittel", + "scenes.apps.drive.no_file_alert": "Du har ingen programmer som lar deg lage en fil.", + "scenes.apps.drive.no_storage_app_alert": "Du har ingen applikasjoner som lar deg legge til ekstern lagring.", + "scenes.apps.drive.remove_definitely_menu": "Slett permanent", + "scenes.apps.drive.restore_menu": "Restaurere", + "scenes.error_on_twake": "\"Houston vi har et problem\"", + "scenes.app.workspaces.components.skip": "Hopp over", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Fjern fra kanalen", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Lag en kanal", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Bli med i en kanal", + "components.upload.drop_files.toaster.error": "Du kan ikke laste opp flere enn {{$1}}-filer", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Lagt til {{$1}} i bedriften din", + "scenes.apps.account.account.menu_title": "Regnskap", + "components.calendar.repetition.on": "På", + "scenes.app.workspaces.create_company.group_data.title": "Vi skal være raske - vi trenger bare litt statistisk informasjon.", + "scenes.apps.drive.new_file_menu": "Ny fil", + "scenes.apps.drive.new_file_title": "Ny fil", + "scenes.apps.drive.new_external_storage": "Ny ekstern lagring", + "scenes.apps.drive.new_folder_title": "Ny mappe", + "scenes.apps.drive.unconfigured_tab": "Denne fanen er ikke konfigurert ennå.", + "scenes.apps.messages.messageslist.go_last_message_button": "Gå til siste melding", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Nye meldinger", + "scenes.login.verifymail.signin_button": "Logg Inn", + "scenes.login.verifymail.success": "E-posten din ble bekreftet!", + "scenes.login.verifymail.verification_waiting": "Venter på bekreftelse...", + "scenes.no_panic": "Ikke få panikk! Bare last inn denne siden på nytt for å fikse Twake.", + "services.apps.calendar.deadline_icon": "Frist", + "services.apps.calendar.event_icon": "Begivenhet", + "services.apps.calendar.move_icon": "Bevege seg", + "services.apps.calendar.reminder_icon": "Påminnelse", + "services.apps.messages.no_app": "Denne applikasjonen eksisterer ikke.", + "services.apps.messages.no_command_possible": "Vi kan ikke utføre kommandoen '{{$1}}' fordi '{{$2}}' ikke eksisterer eller ikke tillater å lage kommandoer.", + "services.user.notification_parameters_update_alert": "Varslingsinnstillingene er oppdatert.", + "services.user.update_password_alert": "Passordet ditt er oppdatert.", + "scenes.apps.tasks.board.tasks.use_starttime": "Bruk starttid", + "scenes.apps.tasks.board.tasks.in_list": "På listen", + "scenes.apps.tasks.board.starts": "Starter", + "scenes.apps.tasks.board.ends": "Skal gjøres for", + "scenes.apps.tasks.board.list_name": "Liste navn", + "scenes.app.popup.sync_calendar": "Synkroniser kalenderne dine.", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "Logoen til selskapet", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "Rediger firmabilde ", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "Avbryt invitasjonen", + "scenes.apps.account.account.fullname": "Fullt navn", + "login.email_login": "E-post/pålogging", + "scenes.apps.account.account.password_for_user": "Passord for brukeren din", + "scenes.apps.account.account.send_info": "Send denne legitimasjonsinformasjonen til brukeren din.", + "scenes.apps.account.account.save": "Lagre konto", + "scenes.apps.account.message_temporary": "En midlertidig konto fungerer som en vanlig Twake-konto, men du oppretter passordet og du vil kunne tilbakestille det om nødvendig.", + "scenes.apps.account.message_user_signin": "Brukeren din kan når som helst logge på med den samme e-posten og endre den midlertidige kontoen til en vanlig konto.", + "scenes.app.mainview.link_expired": "Denne offentlige lenken er ugyldig eller har utløpt.", + "scenes.app.mainview.create_account": "Lag arbeidsområdet ditt gratis på ", + "scenes.apps.calendar.modals.reminder_add": "Legg til en påminnelse", + "components.attachmentpicker.add_attachment": "Legg til vedlegg", + "components.input.copied": "Kopiert", + "components.drive.new_versions": "Legg til en ny versjon", + "components.drive.navigators.directory_not_found": "Katalog ikke funnet.", + "components.drive.right_preview.suppress_link": "Undertrykk koblingen", + "components.drive.right_preview.create_link": "Opprett en tilgangslenke", + "components.drive.moove_here": "Flytt her", + "components.drive.modify_uslist": "Endre brukerliste", + "components.tagpicker.tag_name": "Tag navn", + "components.upload.drop_files": "Slipp filene dine her", + "components.workspace.list_manager.no_workspace": "Ingen arbeidsplass", + "components.workspace.list_manager.add": "Legg til arbeidsområder", + "components.workspace.list_manager.current_space": "Nåværende arbeidsområde", + "components.workspace.list_manager.current_company": "Nåværende selskap", + "components.workspace.calendar.invalid": "Ugyldig", + "components.searchpopup.enter_text": "Skriv inn litt tekst for å søke etter Twake.", + "components.searchpopup.loading": "Laster inn flere resultater", + "components.searchpopup.filter_ws": "Filtrer arbeidsområder", + "components.searchpopup.tags": "Tagger", + "components.searchpopup.size": "Størrelse", + "components.searchpopup.creation": "Opprettelse", + "components.searchpopup.update_search": "Oppdater søket", + "components.searchpopup.last_modif": "Siste modifikasjon", + "components.searchpopup.sender": "Avsender", + "components.searchpopup.mentions": "Omtaler", + "components.searchpopup.only_pinned": "Bare festede meldinger", + "components.alert.confirm": "Bekreft handlingen din", + "components.alert.confirm_click": "Bekreft handlingen ved å klikke på OK.", + "components.searchpopup.tasks": "Oppgaver", + "scenes.app.mainview.advanced_search_placeholder": "Avansert søk", + "components.searchpopup.hide_filters": "skjule filtre", + "components.searchpopup.show_filters": "vis filtre", + "components.searchpopup.load_more": "Last inn flere resultater", + "scenes.apps.board.all_boards": "Alle brett", + "components.userlistmanager.no_users": "Ingen brukere.", + "scenes.apps.calendar.reminders": "påminnelse(r)", + "scenes.apps.calendar.video_link": "Klikk for å åpne lenken", + "scenes.app.mainview.discussion": "Diskusjon", + "components.tagpicker.notag": "Ingen tag", + "scenes.apps.tasks.modals.attachments": "Vedlegg", + "components.calendar.calendarselector.from": "Fra", + "scenes.apps.drive.move_text2": "Bevege seg", + "components.attachmentpicker.from_computer": "Fra enheten din", + "components.attachmentpicker.from_twake": "Fra Twake Documents", + "components.attachmentpicker.file": "Fil", + "components.attachmentpicker.remove_attach": "Fjern vedlegg", + "scenes.apps.drive.remove_attachs": "Fjern vedlegg", + "components.drive.elements.see": "Se", + "components.drive.elements.current_name": "Nåværende navn: ", + "scenes.apps.drive.right_preview.public": "Offentlig tilgang", + "components.drive.elements.configurate_mod": "Konfigurer moden...", + "components.drive.elements.manage_version": "Administrer versjoner", + "scenes.app.popup.createcompany.try_again": "Vær så snill, prøv på nytt.", + "scenes.app.popup.appsparameters.pages.title_informations": "Grunnleggende informasjon", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Informasjon knyttet til applikasjonsadministrasjon", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Gjeldende bruker-ID", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Gjeldende arbeidsområde-ID", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Gjeldende gruppe-id", + "scenes.app.mainview.channel_description": "Beskriv kanalen", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Inviter automatisk alle arbeidsområdebrukere til denne kanalen", + "scenes.client.channelbar.channelmemberslist.title": "Brukere i {{$1}}", + "scenes.client.channelbar.channelmemberslist.loader": "Last mer", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Legg til eller søk bruker", + "components.channelworkspacelist.title": "Kanaler", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Søk etter kanal, bruker eller direktemeldinger", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Opprett en ny fane", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "Gi nytt navn til {{$1}}", + "components.connectorslistmanager.add_connectors": "Legg til kontakter", + "components.notifications.hidden_notifications_button.children": "Nye meldinger", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "applikasjon", + "scenes.client.channelbar.channelmemberslist.no_members": "Det er ingen bruker i denne kanalen, du kan invitere dem ved å klikke på Legg til brukere.", + "components.newversion.new_version_component.row.part_2": "vi foreslår at du laster appen på nytt og nyter de nye funksjonene våre!", + "components.newversion.new_version_component.link": "Klikk her for å laste inn på nytt", + "components.newversion.new_version_modal.title": "Ny oppdatering tilgjengelig !", + "scenes.apps.drive.download_all_button": "Last ned alle", + "components.inputs.input_with_select.input.placeholder": "Kanalnavn", + "components.inputs.input_with_select.select.placeholder": "Seksjonsnavn", + "components.inputs.input_with_select.select.no_sections": "Begynn å skrive navnet på din første kanalseksjon.", + "components.inputs.input_with_select.button.tooltip": "Angi en kanalseksjon", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} la til {{$2}} til kanalen", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} fjernet {{$2}} fra kanalen", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} endret beskrivelsen", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} la til en ny kobling {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} fjernet en kobling {{$2}}", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Last mer", + "general.re_send": "Send på nytt", + "general.verify": "Bekrefte", + "components.unverified_account.typography_text_danger": "Du har {{$1}} dag(er) igjen av prøveperioden. Prøvekonto vil bli blokkert etter 7 dager og slettet permanent etter 1 måned etter registrering. Du kan bekrefte kontoen din ved å klikke på \"Bekreft kontoen min\"-knappen i bekreftelses-e-posten vi sendte deg.", + "components.unverified_account.verification_details": "Vi har sendt bekreftelsesdetaljer til", + "components.account_verification_status_sentence": "Kontostatusen din er: {{$1}}", + "components.account_verication_status_unverified": "Ubekreftet", + "components.account_verication_status_blocked": "Låst", + "components.unverified_account.re_send_email": "Har du ikke mottatt e-posten?", + "components.blocked_account.trial_period_over": "Prøveperioden din er over. For å låse opp kontoen din og få tilgang til alle funksjoner, vennligst bekreft kontoen din via e-postbekreftelse", + "components.add_mails_workspace.button": "Begynn å bruke Twake", + "components.add_mails_workspace.title_1": "Legg til noen brukere", + "components.add_mails_workspace.title_2": "Twake er et teamsamarbeidsverktøy, så inviter noen brukere til å teste et arbeidsområde vi har laget for deg.", + "components.add_mails_workspace.text_area_placeholder": "Skriv inn e-poster til brukerne dine*", + "components.verify_mail.title_1": "Gratulerer", + "components.verify_mail.title_2": "Du er en offisiell Twake-bruker nå!", + "components.verify_mail.button": "Legg til bruker", + "components.verify_mail.text": "Først av alt må du bekrefte e-postadressen din. Vi har sendt en bekreftelseslenke til", + "components.verify_mail.paragraph": "Du kan gjøre det senere hvis du vil, men ubekreftede kontoer har bare tilgang til en begrenset versjon av Twake", + "services.console_services.toaster.add_emails_error": "Feil ved å legge til e-post(er)", + "services.console_services.toaster.add_email_error_message": "Feil under tillegging av {{$1}}", + "services.console_services.toaster.success_verify_email": "En bekreftelseslenke er sendt til e-postkontoen din", + "scenes.app.popup.workspaceparameter.edit_from_console": "Se i konsoll", + "services.console_services.toaster.success_invite_emails": "Vellykket lagt til {{$1}} bruker(e)", + "scenes.client.channels_bar.modals.guest_management.title": "Administrer gjester i {{$1}}", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Søk etter gjester eller ventende e-poster", + "scenes.client.channels_bar.modals.guest_management.tips": "Begynn å legge til eller søke etter e-post ved å bruke inndataene ovenfor", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Mail sendt", + "general.user.role.company.admin": "Bedriftsadministrator", + "general.user.role.company.member": "Medlem", + "general.user.role.company.guest": "Gjest", + "general.user.deleted": "Slettet konto", + "components.richtexteditor.toolbar.bold": "Modig", + "components.richtexteditor.toolbar.underline": "Understrek", + "components.richtexteditor.toolbar.italic": "Kursiv", + "components.richtexteditor.toolbar.strikethrough": "Gjennomstreking", + "components.richtexteditor.toolbar.code": "Kode", + "components.richtexteditor.toolbar.unordered-list": "Punktliste", + "components.richtexteditor.toolbar.ordered-list": "Bestilt liste", + "components.richtexteditor.toolbar.blockquote": "Blockquote", + "components.richtexteditor.toolbar.code-block": "Kodeblokk", + "components.locked_features.locked_history_banner.title": "Du har akkurat nådd meldingsgrensen", + "components.locked_features.locked_history_banner.description": "Din bedrift har mange meldinger! Oppgrader nå for å få tilgang til hele meldingsloggen din.", + "components.locked_features.locked_history_banner.button": "Lære mer", + "components.locked_features.locked_guests_popup.title": "Gjestefunksjonen er låst", + "components.locked_features.locked_guests_popup.subtitle": "Denne funksjonen er ikke tilgjengelig i Twake gratisversjonen", + "components.locked_features.locked_guests_popup.description": "Huff!! Det virker som du ønsker å invitere eksterne brukere til arbeidsområdet ditt. Det kan være lurt å vurdere å oppgradere planen din hvis du ønsker å samarbeide med gjester og eksterne partnere. Utforsk prisalternativene våre og velg det beste alternativet for teamsamarbeidsbehovene dine.", + "components.locked_features.locked_guests_popup.learn_more_button": "Lære mer", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Hopp over for nå", + "components.locked_features.locked_guests_popup.or": "Eller", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Det er et problem med firmaabonnementet ditt. Vennligst ta en titt på din", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Det er et problem med firmaabonnementet ditt. Ta kontakt med eieren eller administratoren av selskapet!", + "components.on_boarding.company_billing_banner.link": "selskapets abonnementsplan", + "components.on_boarding.popups.blocked_company.title": "Firmaet ditt er låst på grunn av et betalingsproblem", + "components.on_boarding.popups.blocked_company.description": "Ditt abonnement på Twake har utløpt. Ta kontakt med eieren eller administratoren av firmaet ditt for å fornye det og være i stand til å kommunisere med teamet ditt igjen!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Vil du lære mer om bedriftens abonnementsplan?", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Klikk her", + "components.on_boarding.popups.blocked_company.or": "Eller", + "components.on_boarding.popups.blocked_company.company_selector": "Bytt til et annet selskap", + "scenes.apps.tasks.select_user_button": "Se oppgaver for en annen bruker", + "scenes.apps.tasks.select_user": "Søk bruker", + "scenes.apps.messages.input.attach_file.from_computer": "Fra datamaskinen", + "scenes.app.popup.workspaceparameter.pages.table_title": "Navn", + "scenes.client.main_view.main_header.search_input": "Søk", + "scenes.apps.drive.new_link_title": "Ny lenke", + "scenes.apps.drive.default_link_name": "Uten navn", + "components.emoji_picker.input_search_placeholder": "Søk", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Du kan ikke legge til flere enn {{$2}} filer i en melding", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Du slettet denne meldingen", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} slettet meldingen hans", + "components.member.user_parts.and_more_user_text": " og {{$1}} flere brukere", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Opprett en privat kanal", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " i stedet", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Du kan ikke legge til mer enn 10 brukere", + "general.uploading": "Laster opp", + "components.emoji_picker.categories.not_found": "Ingen emoji funnet", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Rolle", + "general.email": "E-post", + "components.locked_features.locked_workspace_popup.title": "Du kan ikke opprette flere arbeidsområder", + "components.locked_features.locked_workspace_popup.subtitle": "I gratisversjonen kan du bare ha ett arbeidsområde i bedriften din.", + "components.locked_features.locked_workspace_popup.text": "Huff!! Ønsker du å skape et nytt arbeidsområde i din bedrift? Det kan være lurt å vurdere å oppgradere planen din. Utforsk våre prisalternativer og velg det beste valget for teamsamarbeidsbehovene dine.", + "components.locked_features.locked_only_office_popup.title": "Du kan ikke redigere denne filen", + "components.locked_features.locked_only_office_popup.subtitle": "I gratisversjonen kan du ikke bruke onlyoffice.", + "components.locked_features.locked_drive_popup.title": "Du har akkurat nådd kjøregrensen", + "components.locked_features.locked_drive_popup.subtitle": "I gratisversjonen kan du kun lagre 6 GB.", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Meldingsnummer", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "På gratisversjonen av Twake kan du ikke få tilgang til mer enn de {{$1}} nyere meldingene.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Vis flere planer", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "Ny privat diskusjon", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Ingen private meldinger. Inviter brukere!", + "scenes.app.channelsbar.channelsuser.private_messages": "Direktemeldinger", + "scenes.app.channelsbar.channelsworkspace.channel_title": "KANALER", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "FAVORITER", + "scenes.app.channelsbar.channelsworkspace.create_channel": "Lag en kanal", + "scenes.app.channelsbar.channelsworkspace.no_channel": "Du har ikke blitt med i noen kanal ennå", + "scenes.app.channelsbar.modify_channel_menu": "Rediger kanal", + "scenes.app.channelsbar.guest_management": "Gjesteledelse", + "scenes.app.channelsbar.read_sign": "Merk som lest", + "scenes.app.channelsbar.unread_sign": "Merk som ulest", + "scenes.app.channelsbar.channel_leaving": "Forlat kanalen", + "scenes.app.channelsbar.channel_removing": "Slett kanal", + "scenes.app.channelsbar.company_invitation_alert_title": "Du inviteres til selskapet ", + "scenes.app.channelsbar.initial_instructions_tutorial": "Velg et fornavn, et navn og et profilbilde.", + "scenes.app.channelsbar.installation_desktop_tutorial": "Installer skrivebordsapplikasjonen", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Inviter brukere til arbeidsområdet ditt.", + "scenes.app.channelsbar.public_channel_label": "Offentlig", + "scenes.app.channelsbar.private_channel_label": "Privat", + "scenes.app.channelsbar.sending_message_instruction": "Send din første melding i en diskusjon", + "scenes.app.channelsbar.tutorial_alert": "Vil du aldri vise denne rammen igjen?", + "scenes.app.channelsbar.welcome": "Velkommen til Twake", + "scenes.app.channelsbar.welcoming_message_subtitle": "Bli en Twake-proff med bare noen få klikk!", + "scenes.app.mainview.instruction_current_tab": "Start med å velge en kanal til venstre.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Du har ingen kobling som kan koble til en kanal.", + "scenes.app.mainview.tabs.rename": "Gi nytt navn", + "scenes.app.mainview.tabs.searching_connectors": "Søk etter koblinger...", + "scenes.app.popup.adduser.adresses_message": "Vennligst skill adressene med komma eller mellomrom. Husk at Twake kan begrense antall invitasjoner basert på abonnementet ditt.", + "scenes.app.popup.appsparameters.pages._app_identity": "Søknadens identitet", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Test utseendet til Twacode-meldingene dine", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Søknaden din er publisert, du kan ikke redigere den.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Bruk * i utviklingen for å tillate alle IP-adresser.", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "Min fantastiske app", + "scenes.app.popup.appsparameters.pages.api_data_description": "Nyttige data for Twake API.", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "API-innstillinger", + "scenes.app.popup.appsparameters.pages.app_name_label": "Programnavn", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Alle ledere av dette selskapet vil kunne redigere denne applikasjonen.", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Definer hva applikasjonen din kan redigere og lese.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Applikasjonsrettigheter", + "scenes.app.popup.appsparameters.pages.app_update": "Oppdater appen {{$1}} (appen brukes {{$2}} ganger.)", + "scenes.app.popup.appsparameters.pages.application_title": "applikasjon", + "scenes.app.popup.appsparameters.pages.apps_title": "Dine applikasjoner og koblinger", + "scenes.app.popup.appsparameters.pages.automatique_label": "Automatisk", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "Hvis du aktiverer 'Automatisk', vil denne applikasjonen automatisk bli lagt til de neste arbeidsområdene til dette selskapet.", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "Tillatte IP-adresser", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "Publiseringen av søknaden din venter for øyeblikket på validering av Twake-teamet.", + "scenes.app.popup.appsparameters.pages.button_force": "Kraft i hele selskapet", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "Hendelse av typen «{{$1}}» og id «{{$2}}» med passive «{{$3}}»", + "scenes.app.popup.appsparameters.pages.company_label": "Bedriftseier", + "scenes.app.popup.appsparameters.pages.configuration_label": "Konfigurasjon", + "scenes.app.popup.appsparameters.pages.create_app_button": "Opprett en applikasjon", + "scenes.app.popup.appsparameters.pages.create_my_app": "Opprett søknaden min", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Du har ikke opprettet en app ennå. Før du oppretter en applikasjon eller kobling, sørg for at den ikke allerede eksisterer i vårt applikasjonsmarked.", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "Slett søknad", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "Farlig sone", + "scenes.app.popup.appsparameters.pages.description_label": "Beskrivelse", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Applikasjoner utviklet av selskapet", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Lar deg definere hvor applikasjonen din skal være synlig.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Skjerminnstillinger", + "scenes.app.popup.appsparameters.pages.error_check_needed": "Det har oppstått en feil; sjekk informasjonen din.", + "scenes.app.popup.appsparameters.pages.error_message": "Dette navnet er allerede brukt av en annen applikasjon; vennligst velg en annen.", + "scenes.app.popup.appsparameters.pages.error_user_code": "feil", + "scenes.app.popup.appsparameters.pages.event_subtitle": "arrangementer", + "scenes.app.popup.appsparameters.pages.filter_information": "Dette filteret begrenser bruken av API-nøkkelen til kun servere i koblingen din.", + "scenes.app.popup.appsparameters.pages.go_back": "Tilbake", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Dette navnet er allerede i bruk av en annen applikasjon. Vennligst velg en annen.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Forenklet navn", + "scenes.app.popup.appsparameters.pages.installation": "Installer.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Start med å skrive meldingen i JSON-format.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Intern søknad", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Rediger de offentlige dataene til applikasjonen din.", + "scenes.app.popup.appsparameters.pages.new_app_title": "Ny søknad", + "scenes.app.popup.appsparameters.pages.ok_user_code": "ok", + "scenes.app.popup.appsparameters.pages.optimal_format": "Optimalt format: 48x48px.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "Den upubliserte applikasjonen vil kun fungere i din bedrift. Hvis du ønsker å gjøre det tilgjengelig for alle Twake-brukere, aktiver dette alternativet.", + "scenes.app.popup.appsparameters.pages.public_availability_application": "Offentlig søknad", + "scenes.app.popup.appsparameters.pages.public_login_label": "Offentlig identifikator", + "scenes.app.popup.appsparameters.pages.publication_description": "Bestem synligheten til søknaden din.", + "scenes.app.popup.appsparameters.pages.publication_label": "Utgivelse", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Publiser søknad", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Les privilegier", + "scenes.app.popup.appsparameters.pages.remove_app": "Slett applikasjonen {{$1}} permanent.", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Fjern fra hele selskapet", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Fjern fra arbeidsområdet", + "scenes.app.popup.appsparameters.pages.show_button": "Forestilling", + "scenes.app.popup.appsparameters.pages.status_tilte": "Stat", + "scenes.app.popup.appsparameters.pages.string_information": "Denne strengen identifiserer applikasjonen din og vil bli brukt i meldingskommandoer.", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode tester", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "URL til arrangementsmottak", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Det forenklede navnet på applikasjonen din brukes allerede av en annen applikasjon. Vennligst endre den.", + "scenes.app.popup.appsparameters.pages.update_button": "Oppdater", + "scenes.app.popup.createworkspacepage.add_subtitle": "Trenger mer rom?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Opprett et nytt arbeidsområde", + "scenes.app.popup.createworkspacepage.placeholder_name": "Navn på arbeidsområdet", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Still inn frekvensen for mobilvarsler.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Hyppighet av varsler", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Uthev følgende søkeord:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Angi frekvensen for e-postvarsler.", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Vis innhold i private meldinger", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Skjul innhold i private meldinger", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Velg en periode der du ikke mottar varsler.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Ikke forstyrr om natten", + "scenes.app.popup.userparameter.pages.notif_content_label": "Innhold i varsler", + "scenes.app.mainview.quick_search_placeholder": "Raskt søk", + "scenes.app.popup.userparameter.personnal_workspaces_title": "Arbeidsområdene dine", + "scenes.app.popup.workspaceparameter.admin_current_status": "Du er en administrator.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Du er en arbeidsområdeadministrator.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Du er en bedriftsadministrator.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Slett arbeidsområde", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Du må være alene på arbeidsområdet for å fjerne det. Fjern samarbeidspartnerne dine og prøv på nytt.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "For å bekrefte at du vil slette dette arbeidsområdet, skriv inn navnet nedenfor og trykk på Slett.", + "scenes.app.popup.workspaceparameter.pages.enter": "Tast inn ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Få tilgang til applikasjonene og koblingene dine", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Arbeidsområde moderator", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Du kan ikke forlate arbeidsområdet, fordi du er den siste administratoren. Du kan definere en ny administrator eller slette/arkivere dette arbeidsområdet.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Alle applikasjoner", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Din bedrifts applikasjoner", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Endre navnet på dette selskapet", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "Navn på selskapet", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "konfigurasjon", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Konfigurer", + "scenes.app.popup.workspaceparameter.pages.description": "Beskrivelse", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Applikasjoner utviklet av selskapet", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Vis preferanser", + "scenes.app.popup.workspaceparameter.pages.install_button": "Installere", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Installer applikasjonen i dette arbeidsområdet.", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Apper installert i dette arbeidsområdet {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Applikasjoner installert i andre områder av selskapet {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Installerte applikasjoner", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Det oppsto en feil under invitasjonen av følgende brukere: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Sjekk at brukernavnet eller e-posten som brukes er gyldig.", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Tilgang til webhooks", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Maksimal størrelse 5 MB.", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Fjern fra dette arbeidsområdet", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "arbeidsområde", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Skrivetilgang", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Dine søknader", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Betalinger og abonnementer", + "scenes.app.workspacesbar.components.change_company_title": "Bytt selskap", + "scenes.app.workspacesbar.components.create_company_menu": "Opprett et selskap", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} innstillinger", + "scenes.apps.calendar.add_calendar_menu": "Legg til en kalender", + "scenes.apps.calendar.connectors_menu": "Koblinger...", + "scenes.apps.calendar.connectors_search_menu": "Søk etter koblinger...", + "scenes.apps.calendar.create_calendar_title": "Lag en kalender", + "scenes.apps.calendar.edit_calendar_title": "Rediger kalenderen", + "scenes.apps.calendar.export_title": "Eksport", + "scenes.apps.calendar.export_view_menu": "Eksporter visningen...", + "scenes.apps.calendar.ics_download_menu": "Last ned en ICS-fil", + "scenes.apps.calendar.ics_subscription_menu": "Få en ICS-abonnementslenke", + "scenes.apps.calendar.modals.advanced_options": "Avanserte instillinger", + "scenes.apps.calendar.modals.participants_event": "Deltakere", + "scenes.apps.calendar.modals.reminders": "Påminnelser", + "scenes.apps.calendar.modals.remove_button": "Slett", + "scenes.apps.calendar.modals.remove_event_button": "Slett hendelsen", + "scenes.apps.calendar.modals.remove_event_text": "Vil du slette arrangementet?", + "scenes.apps.calendar.modals.title_placeholder": "Tittel", + "scenes.apps.calendar.modify_calendar_menu": "Rediger kalenderen", + "scenes.apps.calendar.month_option": "Måned", + "scenes.apps.calendar.my_calendar": "Min kalender", + "scenes.apps.calendar.my_calendar_label": "Min kalender", + "scenes.apps.calendar.my_calendar_menu": "Min kalender", + "scenes.apps.calendar.no_calendar_text": "Du har ikke angitt noen kalendere for dette arbeidsområdet.", + "scenes.apps.calendar.no_connectors_menu_text": "Du har ingen koblinger som kan kobles til en kalender.", + "scenes.apps.calendar.remove_calendar_confirmation": "Vil du slette kalenderen og dens hendelser permanent?", + "scenes.apps.calendar.today_menu": "I dag", + "scenes.apps.calendar.week_option": "Uke", + "scenes.apps.calendar.workspace": "Arbeidsområde", + "scenes.apps.calendar.workspace_label": "Dette arbeidsområdet", + "scenes.apps.calendar.workspace_menu": "Arbeidsområde", + "scenes.apps.drive.add_button": "Legge til", + "scenes.apps.drive.message_added_file": "{{$1}} sendte {{$2}}.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} sendte flere filer.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} sendte en fil.", + "scenes.apps.drive.choose_folder_button": "Velg en katalog", + "scenes.apps.drive.choose_file_button": "Velg en fil", + "scenes.apps.drive.create_folder_button": "Skape", + "scenes.apps.drive.download_button": "nedlasting", + "scenes.apps.drive.open_link": "Åpne lenken i nytt vindu", + "scenes.apps.drive.files_subtitle": "Filer", + "scenes.apps.drive.folder_subtitle": "Mapper", + "scenes.apps.drive.go_out_trash_menu": "Legg igjen søppel", + "scenes.apps.drive.go_trash_menu": "Gå til søpla", + "scenes.apps.drive.import_from_computer_menu": "Last opp fra datamaskinen", + "scenes.apps.drive.move_text": "Bevege seg", + "'": "'", + "\"": "\"", + "login.login_error": "Feil under pålogging", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Ingen har invitert deg til et arbeidsområde ennå.", + "scenes.apps.messages.message.types.no_message_in_thread": "Ingen har svart ennå.", + "login.create_account": "Opprett konto", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Standard arbeidsområde", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Inviter automatisk alle arbeidsområdebrukere til denne kanalen", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Du er i ferd med å slette {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Du har fortsatt {{$1}} medlemmer i {{$2}}. Du bør fjerne alle medlemmene for å kunne slette dette arbeidsområdet.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Jeg forstår at alle meldingene og filene på arbeidsområdet mitt vil bli slettet.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Maks logostørrelse er 5mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Dårlig format, kun png gif og jpg er tillatt", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Ukjent feil", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Feil", + "scenes.app.channelsbar.currentuser.reset": "Nullstille", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Skriv minst tre bokstaver for å vise brukere", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Ingen bruker funnet", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Ingen emoji funnet", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Ingen kommando funnet", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} skriver...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} og {{$2}} skriver...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} og {{$3}} flere brukere skriver...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Firmaet ditt har nådd sin maksimale grense på {{$1}} medlemmer. Vær så snill ", + "components.locked_features_components.locked_invite_alert.message_link": "oppgradere bedriften din", + "components.locked_features_components.locked_invite_alert.message_part_2": " å invitere flere medlemmer.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " kontakt eieren eller administratoren av bedriften din.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Se alle firmamedlemmene mine på konsollen", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Fjernet applikasjonen {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Feil under fjerning av applikasjonen {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Vellykket {{$1}}-applikasjon!", + "scenes.app.integrations_parameters.add_application": "Ny integrasjon", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Utviklerinnstillinger", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake API-dokumentasjonen", + "scenes.app.popup.appsparameters.pages.app.private_key": "Privat nøkkel", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Beskriv søknaden din med noen få ord", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Ny integrasjon", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Jeg forstår at eieren og administratorene av dette selskapet vil kunne endre og publisere denne applikasjonen.", + "twake.application.access.title": "Velg de riktige omfangene for applikasjonen din.", + "twake.application.access.no_default_scopes_available'": "Denne integrasjonen har ingen {{$1}}-tilgang", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Hvis du ikke vet hvordan du fyller disse, gå til ", + "components.rich_text_editor.plugins.suggestions.loading": "Ser etter mer", + "components.open_desktop_popup.subtitle": "åpnet i Twake-appen", + "components.open_desktop_popup.open_here_link": "Åpne her i stedet", + "molecules.download_banner.title": "Få mest mulig ut av Twake, last ned skrivebordsappen nå", + "molecules.download_banner.download_button": "Last ned desktop app", + "scenes.app.channelsbar.channel_copy_link": "Kopier kanallinken", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Vellykket oppdatert", + "components.searchpopup.no_results_for": "Det var ingen resultater for", + "components.searchpopup.try_new_search": "Prøv et nytt søk", + "components.searchpopup.all": "Alle", + "components.searchpopup.chats": "Chatter", + "components.searchpopup.media": "Media", + "components.searchpopup.files": "Filer", + "components.searchpopup.recent_chats": "Nylige chatter", + "components.searchpopup.recent_media": "Nylige medier", + "components.searchpopup.recent_files": "Nylige filer", + "components.searchpopup.recent_channels_and_contacts": "Nylige kanaler og kontakter", + "components.searchpopup.header_title": "Søk", + "components.searchpopup.scope.company": "i alle selskap", + "components.searchpopup.scope.channel": "i denne kanalen", + "components.searchpopup.channels": "Kanaler", + "components.searchpopup.messages": "Meldinger" +} diff --git a/twake/frontend/public/locales/ru.json b/twake/frontend/public/locales/ru.json index 228b5f4c87..100fd9927a 100644 --- a/twake/frontend/public/locales/ru.json +++ b/twake/frontend/public/locales/ru.json @@ -8,8 +8,8 @@ "general.back": "Назад", "general.confirm": "Подтвердить", "general.delete": "Удалить", - "general.archive": "Архив", - "general.unarchive": "Снять с архивы", + "general.archive": "Архивировать", + "general.unarchive": "Разархивировать", "general.help": "Помощь", "general.help.support": "Поддержка", "general.help.documentation": "Документация", @@ -19,60 +19,60 @@ "general.add": "Добавить", "general.connexion_status.disconnected": "Вы не в сети", "general.connexion_status.connected": "Вы в сети", - "general.connexion_status.connecting": "Переподключение...", - "scenes.app.side_app.messages_thread_title": "{{$1}} • Ответы на сообщение", - "scenes.app.workspaces.create_company.group_data": "Настройте вашу новую группу", + "general.connexion_status.connecting": "Переподключение…", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Ветка сообщений", + "scenes.app.workspaces.create_company.group_data": "Настроить новую группу", "scenes.app.workspaces.create_company.group_data.group_type": "Вид группы", "scenes.app.workspaces.create_company.group_data.group_type.company": "Компания или отдел компании", "scenes.app.workspaces.create_company.group_data.group_type.public_organization": "Общественная организация", "scenes.app.workspaces.create_company.group_data.group_type.university_school": "Университет или школа", - "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Общество, клуб или благотворительность", - "scenes.app.workspaces.create_company.group_data.group_type.other_group": "Другое", + "scenes.app.workspaces.create_company.group_data.group_type.society_club_charity": "Общество, клуб или благотворительная организация", + "scenes.app.workspaces.create_company.group_data.group_type.other_group": "Прочее", "scenes.app.workspaces.create_company.group_data.group_size": "Размер группы", - "scenes.app.workspaces.create_company.group_data.group_size.less_3": "Менее 4-х человек", - "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4 - 10 человек", - "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11 - 49 человек", - "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50 - 99 people", - "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100 - 499 человек", - "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500 - 999 человек", - "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000 - 4999 человек", - "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "Больше 5000 человек", - "scenes.app.workspaces.create_company.group_data.group_main_activity": "Главная деятельность", - "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Еда", + "scenes.app.workspaces.create_company.group_data.group_size.less_3": "Менее 4 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.4_10": "4 - 10 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.10_50": "11 - 49 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.50_100": "50 - 99 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.100_500": "100 - 499 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.500_1000": "500 - 999 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.1000_5000": "1000 - 4999 пользователей", + "scenes.app.workspaces.create_company.group_data.group_size.5000_more": "Более 5000 пользователей", + "scenes.app.workspaces.create_company.group_data.group_main_activity": "Основной вид деятельности", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "Продукты питания", "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "Банк / страхование", - "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Полиграфическая фирма / Бумажная фабрика", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "Полиграфия / Печать газет", "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "Строительство / Строительные материалы", "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "Недвижимое имущество", "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "Материалы", "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "Химия", - "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Торговля", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "Торговля / Коммерция / Распределение", "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Публикации / Коммуникации / Мультимедиа", - "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Электроника / Электричество / Энергия", - "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Исследования и советы", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "Электроника / Электричество / Энергетика", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "Исследования и консалтинг", "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "Фармацевтическая промышленность", - "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "информационная технология / Телеком", - "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Машины / Автомобили", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "Информационные технологии / Телесвязь", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "Машинное оборудование / Автомобили", "scenes.app.workspaces.create_company.group_data.group_main_activity.business_services": "Бизнес-услуги", - "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Развлечение", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "Развлечения", "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "Текстиль / Одежда / Обувь", "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Транспорт / Логистика", - "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Исследование", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "Исследования", "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "Образование", - "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Администрация", - "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "Другое", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Управление", + "scenes.app.workspaces.create_company.group_data.group_main_activity.other": "Прочее", "components.application.messages": "Сообщения", "components.drive_dropzone.uploading": "Загрузка...", - "components.user_picker.modal_no_result": "Результат не найден", - "components.users_picker.add_me": "Меня добавить", - "scenes.app.workspaces.create_company.invitations.title": "Настройте ваше рабочее пространство.", - "scenes.app.header.disconnected": "Вы отключены", + "components.user_picker.modal_no_result": "Результатов не найдено", + "components.users_picker.add_me": "Добавить меня", + "scenes.app.workspaces.create_company.invitations.title": "Настройте вашу рабочую среду.", + "scenes.app.header.disconnected": "Соединение отсутствует", "scenes.app.header.disconnected.reload": "Перезагрузить", "scenes.app.header.alt_notifications": "Уведомления", "scenes.apps.calendar.calendar.week_btn": "Неделя", "scenes.apps.calendar.calendar.list_btn": "Список", "scenes.apps.calendar.event_edition.deadline_tag": "Крайний срок", "scenes.apps.calendar.event_edition.checkbox_all_day": "Весь день", - "scenes.apps.calendar.event_edition.title_confidentiality": "Участники", + "scenes.apps.calendar.event_edition.title_confidentiality": "Конфиденциальность", "scenes.apps.calendar.event_view.article_until": "до", "scenes.apps.calendar.calendar_modal.participants": "Участники", "scenes.apps.calendar.calendar_modal.placeholder": "Имя", @@ -93,16 +93,16 @@ "scenes.apps.messages.chatbox.chat.delete_message": "Удалить данное сообщение", "scenes.apps.messages.chatbox.chat.delete_message_btn": "Удалить сообщение", "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "Название", - "scenes.apps.messages.left_bar.stream.add_to_favorites": "Добавить канал в избранное", - "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Удалить из Избранного", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Добавить в избранное", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Удалить из избранного", "scenes.apps.messages.left_bar.stream.notifications": "Уведмления...", - "scenes.apps.messages.left_bar.stream.notifications.all": "Всех сообщений", + "scenes.apps.messages.left_bar.stream.notifications.all": "Все сообщения", "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} и {{$3}}", "scenes.apps.messages.left_bar.stream.notifications.me": "только {{$1}}", - "scenes.apps.messages.left_bar.stream.notifications.never": "Никокого сообщения", - "scenes.apps.parameters.workspace_sections.workspace": "Рабочее пространство", + "scenes.apps.messages.left_bar.stream.notifications.never": "Никогда", + "scenes.apps.parameters.workspace_sections.workspace": "Рабочая среда", "scenes.apps.parameters.workspace_sections.members": "Участники", - "scenes.apps.parameters.group_sections.workspaces": "Рабочие пространства", + "scenes.apps.parameters.group_sections.workspaces": "Рабочие среды", "scenes.apps.parameters.group_sections.apps": "Приложения", "scenes.apps.account.title": "Параметры аккаунта", "scenes.apps.account.account.menu_title": "Аккаунт", @@ -110,39 +110,39 @@ "scenes.apps.account.account.firstname": "Имя", "scenes.apps.account.account.lastname": "Фамилия", "scenes.apps.account.account.username": "Имя пользователя", - "scenes.apps.account.account.change_username": "Измените ваше имя пользователя.", - "scenes.apps.account.account.emails": "Электронные почты", - "scenes.apps.account.account.main_email": "Главная электронная почта\"", - "scenes.apps.account.account.email_add": "Добавить новую почту", - "scenes.apps.account.account.email_add_modal.invalid_code": "Этот код недействителен", + "scenes.apps.account.account.change_username": "Изменить имя пользователя.", + "scenes.apps.account.account.emails": "Аккаунты электронной почты", + "scenes.apps.account.account.main_email": "Основной аккаунт электронной почты", + "scenes.apps.account.account.email_add": "Добавить новый аккаунт электронной почты", + "scenes.apps.account.account.email_add_modal.invalid_code": "Данный код недействителен", "scenes.apps.account.account.password": "Пароль", "scenes.apps.account.account.password_modal.old_password": "Текущий пароль", "scenes.apps.account.account.password_modal.password": "Новый пароль", - "scenes.apps.account.account.password_modal.bad_old_password": "Прежний пароль неверен.", - "scenes.apps.account.account.password_modal.bad_password": "Ваши пароли не совпадают или слишком малы, пожалуйста, введите пароль не менее чем из 8 символов.", + "scenes.apps.account.account.password_modal.bad_old_password": "Старый пароль введен неверно.", + "scenes.apps.account.account.password_modal.bad_password": "Ваши пароли не совпадают или содержат недостаточно символов. Пожалуйста, введите пароль не менее чем из 8 символов.", "scenes.apps.account.account.logout": "Выйти", "scenes.apps.account.languages.text": "Сменить язык Twake.", "scenes.apps.account.notifications.title": "Уведомления", "scenes.apps.account.notifications.keywords_subtitle": "Ключевые слова", "scenes.apps.account.notifications.keywords_placeholder": "разработка, Wi-Fi, код, ...", - "scenes.apps.account.notifications.disturb_option_a": "Не посылайте мне push-уведомления между ", + "scenes.apps.account.notifications.disturb_option_a": "Не отправлять мне push-уведомления между ", "scenes.apps.account.notifications.disturb_option_b": " и ", - "scenes.apps.account.notifications.disturb_option_c": " (локальный часовой пояс)", + "scenes.apps.account.notifications.disturb_option_c": " (часовой пояс)", "scenes.apps.account.notifications.devices_subtitle": "Уведомления на устройствах", - "scenes.apps.account.notifications.devices_option_ever": "Всегда отправляйте мне push-уведомления", - "scenes.apps.account.notifications.devices_option_inactive": "Отправляйте мне уведомления на телефон, когда я неактивен на рабочем столе", - "scenes.apps.account.notifications.devices_option_never": "Никогда не посылайте мне push-уведомления", + "scenes.apps.account.notifications.devices_option_ever": "Всегда отправлять мне push-уведомления", + "scenes.apps.account.notifications.devices_option_inactive": "Отправлять мне уведомления на телефон, когда я неактивен в десктопной версии", + "scenes.apps.account.notifications.devices_option_never": "Никогда не отправлять мне push-уведомления", "scenes.apps.account.notifications.privacy_subtitle": "Конфиденциальность", "scenes.apps.account.notifications.mail_subtitle": "Уведомления по электронной почте", "scenes.apps.parameters.group_sections.apps.badge_extension": "Расширение", "scenes.apps.parameters.workspace_sections.members.members": "Участники", - "scenes.apps.parameters.workspace_sections.members.pending": "Члены, ожидающие решения", + "scenes.apps.parameters.workspace_sections.members.pending": "Письма, ожидающие обработки", "scenes.apps.parameters.workspace_sections.members.invite": "Пригласить новых участников", "scenes.apps.parameters.workspace_sections.members.invite_btn": "Добавить участников", "scenes.apps.tasks.boards": "Доски", - "scenes.apps.tasks.connectors_menu": "Разъёмы...", - "scenes.apps.tasks.connectors_search_menu": "Поиск разъёмов..", - "scenes.apps.tasks.no_connectors_menu_text": "У вас нет разъёмов, которые могут подключаться к календарю.", + "scenes.apps.tasks.connectors_menu": "Расширения...", + "scenes.apps.tasks.connectors_search_menu": "Поиск расширений...", + "scenes.apps.tasks.no_connectors_menu_text": "У вас нет расширений, которые могут подключаться к календарю.", "scenes.apps.tasks.unconfigured_tab": "Эта вкладка еще не настроена.", "scenes.apps.tasks.choose_board_button": "Выберите доску", "scenes.apps.tasks.new_board.title": "Новая доска", @@ -150,42 +150,42 @@ "scenes.apps.tasks.task": "Задача", "scenes.apps.tasks.no_tasks": "У вас нет активных задач", "scenes.apps.tasks.task_status.todo": "Список задач", - "scenes.apps.tasks.task_status.current": "Текущий", - "scenes.apps.tasks.task_status.done": "Сделано", + "scenes.apps.tasks.task_status.current": "Текущие задачи", + "scenes.apps.tasks.task_status.done": "Выполненные задачи", "scenes.apps.tasks.task.description": "Описание", "scenes.apps.tasks.task.assignees": "Назначенные лица", "scenes.apps.tasks.task.edit.dates": "Даты", "scenes.apps.tasks.list_modal.modify_list": "Изменить список", "scenes.apps.tasks.list_modal.new_list": "Новый список", "scenes.apps.tasks.list_modal.remove": "Удалить список и задачи", - "scenes.apps.tasks.list_modal.predefined_participants": "Предопределенные участники", + "scenes.apps.tasks.list_modal.predefined_participants": "Предполагаемые участники", "scenes.apps.tasks.list_modal.archive_all_tasks": "Архивировать все задачи", "scenes.apps.tasks.list_modal.remove_archived_tasks": "Удалить заархивированные задачи ({{$1}})", "scenes.login.footer.go_to_twake": "Перейти к twakeapp.com", "scenes.login.footer.branding": "Вы находитесь на частном сервере, принадлежащем {{$1}} ({{$2}}). ", "scenes.login.create_account.title": "Создать новый аккаунт", "scenes.login.create_account.email": "Электронная почта", - "scenes.login.create_account.email_used": "Эта электронная почта уже используется.", + "scenes.login.create_account.email_used": "Этот адрес электронной почты уже используется.", "scenes.login.create_account.username": "Имя пользователя", "scenes.login.create_account.username_already_exist": "Это имя пользователя уже используется", - "scenes.login.create_account.fill_in_username": "Вы должны ввести имя пользователя", - "scenes.login.create_account.fill_in_email": "Вы должны заполнить вашу электронную почту с правильным электронным адресом", + "scenes.login.create_account.fill_in_username": "Необходимо ввести имя пользователя", + "scenes.login.create_account.fill_in_email": "Необходимо ввести верный адрес электронной почты", "scenes.login.create_account.too_short_password": "Ваш пароль должен содержать не менее 8 символов.", "scenes.login.create_account.firstname": "Имя", "scenes.login.create_account.newsletter": "Получать информацию о Twake", "scenes.login.create_account.lastname": "Фамилия", "scenes.login.forgot_password.title": "Забыли пароль?", - "scenes.login.forgot_password.text": "Вы получите 9 цифр по электронной почте, чтобы подтвердить вашу личность.", + "scenes.login.forgot_password.text": "Вы получите код из 9 цифр по электронной почте, необходимый, чтобы подтвердить вашу личность.", "scenes.login.forgot_password.email_to_recover": "Электронная почта для восстановления", - "scenes.login.forgot_password.mail_doesnt_exist": "Эта электронная почта не существует", + "scenes.login.forgot_password.mail_doesnt_exist": "Данный адрес электронной почты не существует", "scenes.login.forgot_password.text2": "Вы получите код из 9 символов. Пожалуйста, введите его в поле ниже, чтобы продолжить.", "scenes.login.forgot_password.invalid_code": "Этот код недействителен.", "scenes.login.forgot_password.text3": "Введите новый пароль для вашего аккаунта.", "scenes.login.forgot_password.password": "Пароль", "scenes.login.forgot_password.password2": "Подтвердите пароль", - "scenes.login.forgot_password.password_dont_match": "Ваши пароли не совпадают или слишком малы, пожалуйста, введите пароль, состоящий не менее чем из 8 символов.", + "scenes.login.forgot_password.password_dont_match": "Ваши пароли не совпадают или содержат недостаточно символов, пожалуйста, введите пароль, состоящий не менее чем из 8 символов.", "scenes.login.home.title": "Вход в Twake", - "scenes.login.home.subtitle": "Рад вас видеть", + "scenes.login.home.subtitle": "Добро пожаловать", "scenes.login.home.email": "Почта", "scenes.login.home.unable_to_connect": "Недействительные идентификационные данные", "scenes.login.home.password": "Пароль", @@ -193,153 +193,153 @@ "scenes.login.home.lost_password": "Забыли пароль?", "scenes.login.home.create_account": "Создать аккаунт", "scenes.login.create_account.password": "Пароль", - "scenes.login.create_account.step_1_subtitle": "NНичего более простого, нам просто нужны данные.", - "scenes.login.create_account.step_2_subtitle_a": "Добавьте ваше полное имя, чтобы ваши коллеги узнали вас", - "scenes.login.create_account.step_2_subtitle_b": "Ваш номер телефона остается приватным.", + "scenes.login.create_account.step_1_subtitle": "Все очень просто: нам понадобится кое-какая информация.", + "scenes.login.create_account.step_2_subtitle_a": "Добавьте ваше полное имя, чтобы коллеги могли узнать вас.", + "scenes.login.create_account.step_2_subtitle_b": "Ваш номер телефона не виден другим пользователям.", "scenes.login.create_account.step_3_mail_sent": "Мы отправили вам ссылку для активации по электронной почте.", "scenes.login.create_account.step_3_subtitle": "Последний шаг, мы должны убедиться, что вы не робот!", "scenes.app.workspaces.create_company.company_name.placeholder": "Название компании", "scenes.app.workspaces.create_company.company_name.title_1": "Для начала,", "scenes.app.workspaces.create_company.company_name.title_2": "укажите название вашей компании.", "scenes.app.workspaces.create_company.default_workspace_name": "Главное", - "scenes.app.workspaces.create_company.group_data.title": "Давайте сделаем это быстро, нам просто нужна статистическая информация.", + "scenes.app.workspaces.create_company.group_data.title": "Это не займет много времени: нам просто нужна статистическая информация.", "scenes.app.workspaces.create_company.importations.title_1": "Уже работаете с цифровыми инструментами? Импортируйте или интегрируйте свои инструменты прямо сейчас!", "scenes.app.workspaces.create_company.importations.title_2": "Не волнуйтесь, вы можете сделать это позже!", "scenes.app.workspaces.create_company.invitations.title_2": "Добавьте членов своей команды.", - "scenes.app.workspaces.create_company.title": "Создать мою компанию", - "scenes.app.workspaces.welcome_page.add_secondary_emails": "Добавить вторичную электронную почту", + "scenes.app.workspaces.create_company.title": "Создать свою компанию", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "Добавить еще один аккаунт электронной почты", "scenes.app.workspaces.welcome_page.added_to_company": "Вы были приглашены в ", - "scenes.app.workspaces.welcome_page.create_my_company": "Создать мою компанию", + "scenes.app.workspaces.welcome_page.create_my_company": "Создать свою компанию", "scenes.app.workspaces.welcome_page.lets_go": "Поехали!", "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Возможно, вас пригласили по другому электронному адресу?", - "scenes.app.workspaces.welcome_page.no_company_subtitle": "О ... Похоже, вас еще не пригласили на рабочее место.", - "scenes.app.workspaces.welcome_page.ready_to_work": "Вы готовы работать сейчас.", - "scenes.app.workspaces.welcome_page.see_you_soon": "До скорого.!", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Не вышло... Похоже, вас еще не пригласили в эту компанию.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Все готово для работы.", + "scenes.app.workspaces.welcome_page.see_you_soon": "До скорого!", "scenes.app.workspaces.welcome_page.try_again": "Попробуйте еще раз", - "scenes.app.workspaces.welcome_page.twake_team": "Twake команда", + "scenes.app.workspaces.welcome_page.twake_team": "Twake", "scenes.app.workspaces.welcome_page.welcome_header": "Добро пожаловать в Twake!", - "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Вы можете связать несколько адресов электронной почты с вашим аккаунтом, только один адрес будет использоваться для отправки вам уведомлений.", - "scenes.app.workspaces.welcome_page.main_mail_title": "Главный адрес", - "scenes.app.workspaces.welcome_page.other_mail_title": "Вторичные адреса", - "scenes.app.workspaces.welcome_page.add_new_email": "Добавить электронную почту", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Вы можете связать несколько адресов электронной почты с вашим аккаунтом, только один из них будет использоваться для отправки вам уведомлений.", + "scenes.app.workspaces.welcome_page.main_mail_title": "Основной адрес", + "scenes.app.workspaces.welcome_page.other_mail_title": "Прочие адреса", + "scenes.app.workspaces.welcome_page.add_new_email": "Добавить аккаунт электронной почты", "scenes.app.workspaces.welcome_page.code_verification": "Код проверки", - "scenes.app.workspaces.welcome_page.new_email": "Добавить вторичную электронную почту", + "scenes.app.workspaces.welcome_page.new_email": "Добавить еще один аккаунт электронной почты", "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Мы отправили вам код проверки через {{$1}}", - "scenes.app.workspaces.welcome_page.done": "Я закончил", + "scenes.app.workspaces.welcome_page.done": "Готово", "scenes.login.forgot_password.finished": "Ваш пароль был успешно обновлен.", - "scenes.apps.account.account.description_main": "Ваш главный адрес - это тот, на который Twake отправляет ваши уведомления. Ваши вторичные адреса позволяют автоматически приглашать вас на рабочие места, которые их используют.", - "scenes.apps.account.account.emails.description": "Управляйте различными адресами электронной почты\".", - "scenes.apps.account.account.make_main": "Установить как главная", + "scenes.apps.account.account.description_main": "Ваш основной адрес - это тот, на который Twake отправляет уведомления. Прочие адреса позволяют автоматически приглашать вас в рабочие среды, которые их используют.", + "scenes.apps.account.account.emails.description": "Управляйте различными адресами электронной почты.", + "scenes.apps.account.account.make_main": "Сделать основным", "scenes.apps.account.account.password.description": "Изменить пароль.", "scenes.apps.account.identity": "Личность", - "scenes.apps.account.identity.description": "Измените имя, фамилию и изображение профиля, видимые другими пользователями Twake.", + "scenes.apps.account.identity.description": "Измените имя, фамилию и изображение профиля, видимые другими пользователям Twake.", "scenes.apps.account.preference": "Предпочтения", "general.open": "Открыть", - "scenes.apps.account.thumbnail.max_weight": "Максимальный вес 5 мб", - "scenes.apps.account.account.email_add_modal.confirm": "Подтвердить эту электронную почту", + "scenes.apps.account.thumbnail.max_weight": "Максимальный размер - 5 Мб", + "scenes.apps.account.account.email_add_modal.confirm": "Подтвердить данную электронную почту", "app.name.twake_calendar": "Календарь", "app.name.twake_drive": "Документы", "app.name.twake_tasks": "Задачи", "components.calendar.repetition.everyday": "Ежедневно", "components.calendar.repetition.does_not_repeat": "Однократно", - "components.calendar.repetition.weekly_on": "Еженедельно по {{$1}}", - "components.calendar.repetition.monthly_on": "Ежемесячно по {{$1}} {{$2}}", - "components.calendar.repetition.monthly_on_day": "Ежемесячно в день {{$1}}", + "components.calendar.repetition.weekly_on": "Еженедельно {{$1}}", + "components.calendar.repetition.monthly_on": "Ежемесячно {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "Ежемесячно {{$1}} числа", "components.calendar.repetition.annually_on": "Ежегодно {{$1}}", - "components.calendar.repetition.every_weekday": "Каждый рабочий день (Пон по Пят)", - "components.calendar.repetition.custom": "Особый...", + "components.calendar.repetition.every_weekday": "Каждый рабочий день (с пн по пт)", + "components.calendar.repetition.custom": "Пользовательский вариант...", "components.calendar.repetition.repeat": "Повторять каждый", - "components.calendar.repetition.ends": "Заканчивается", + "components.calendar.repetition.ends": "Окончание", "components.calendar.repetition.never": "Никогда", "components.calendar.repetition.after": "После", "components.calendar.repetition.days": "дня/дней", "components.calendar.repetition.weeks": "недели(ь)", - "components.calendar.repetition.months": "месяц(а)", - "components.calendar.repetition.years": "год/лет", - "components.calendar.repetition.custom_recurrence": "Особое повторение", + "components.calendar.repetition.months": "месяца(ев)", + "components.calendar.repetition.years": "года/лет", + "components.calendar.repetition.custom_recurrence": "Пользовательский вариант", "components.calendar.repetition.occurrence": "Повтор(ы)", "components.calendar.repetition.repeat_on": "Повторить", "scenes.app.channelsbar.currentuser.add_apps": "Поиск приложений", "scenes.app.channelsbar.currentuser.change_my_status": "Изменить мой статус", - "scenes.app.channelsbar.currentuser.collaborateurs": "Сотрудники", - "scenes.app.channelsbar.currentuser.create_workspace_page": "Создать рабочее пространство", - "scenes.app.channelsbar.currentuser.invited_status": "Вы гость.", + "scenes.app.channelsbar.currentuser.collaborateurs": "Пользователи", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Создать рабочую среду", + "scenes.app.channelsbar.currentuser.invited_status": "Вы являетесь гостем.", "scenes.app.channelsbar.currentuser.title": "Настройки аккаунта", - "scenes.app.channelsbar.currentuser.workspace_info": "Вы в рабочем пространстве {{$1}} группы {{$2}}", - "scenes.app.channelsbar.currentuser.workspace_parameters": "Настройки рабочего пространства", + "scenes.app.channelsbar.currentuser.workspace_info": "Вы в рабочей среде {{$1}} группы {{$2}}", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Настройки рабочей среды", "scenes.app.channelsbar.currentuser.logout": "Выход", "scenes.app.channelsbar.currentuser.update": "Обновить", "scenes.app.channelsbar.currentuser.disable_notifications": "Отключить", - "scenes.app.channelsbar.currentuser.disabling_notifications": "Отключить на 1ч", - "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Отключить до завтра в 9 утра", - "scenes.app.channelsbar.currentuser.reactivate_notifications": "Реактивировать", - "scenes.app.channelsbar.currentuser.user_parameter": "Настройки уведомления", + "scenes.app.channelsbar.currentuser.disabling_notifications": "Отключить на 1 час", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Отключить до 9:00 завтрашнего дня", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "Возобновить", + "scenes.app.channelsbar.currentuser.user_parameter": "Настройки уведомлений", "scenes.app.channelsbar.channelsuser.new_private_discussion": "Новое личное сообщение", - "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Никаких личных сообщений, приглашайте своих сотрудников!", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Личных сообщений нет. Приглашайте своих сотрудников!", "scenes.app.channelsbar.channelsuser.private_messages": "Личные сообщения", "scenes.app.channelsbar.channelsworkspace.channel_title": "КАНАЛЫ", - "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "Избранное", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "ИЗБРАННОЕ", "scenes.app.channelsbar.channelsworkspace.create_channel": "Создать канал", "scenes.app.channelsbar.channelsworkspace.no_channel": "Вы еще не присоединились ни к одному каналу", "scenes.app.channelsbar.modify_channel_menu": "Редактировать канал", - "scenes.app.channelsbar.guest_management": "Управление гостями", + "scenes.app.channelsbar.guest_management": "Управление участниками", "scenes.app.channelsbar.read_sign": "Отметить как прочитанное", - "scenes.app.channelsbar.unread_sign": "Отметить как непрочитанный", - "scenes.app.channelsbar.channel_leaving": "покинуть канал", + "scenes.app.channelsbar.unread_sign": "Отметить как непрочитанное", + "scenes.app.channelsbar.channel_leaving": "Покинуть канал", "scenes.app.channelsbar.channel_removing": "Удалить канал", - "scenes.app.channelsbar.company_invitation_alert_subtitle": "Вы можете импортировать эти каналы в свой бизнес, чтобы остаться организованным, нажав на этот кадр.", - "scenes.app.channelsbar.company_invitation_alert_title": "Вы приглашены в компанию", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Для лучшей организации вы можете перенести эти каналы в раздел своего бизнеса, нажав сюда.", + "scenes.app.channelsbar.company_invitation_alert_title": "Вы приглашены в компанию ", "scenes.app.channelsbar.initial_instructions_tutorial": "Выберите имя, фамилию и фотографию профиля.", "scenes.app.channelsbar.installation_desktop_tutorial": "Установить настольное приложение", - "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Пригласите своих сотрудников в ваше рабочее пространство.", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Пригласите своих сотрудников в вашу рабочую среду.", "scenes.app.channelsbar.public_channel_label": "Открытый канал", "scenes.app.channelsbar.private_channel_label": "Частный канал", - "scenes.app.channelsbar.sending_message_instruction": "Отправить первое сообщение в дискуссию", - "scenes.app.channelsbar.tutorial_alert": "Никогда больше не показывать этот кадр?", + "scenes.app.channelsbar.sending_message_instruction": "Отправить первое сообщение в обсуждение", + "scenes.app.channelsbar.tutorial_alert": "Никогда больше не показывать этот блок?", "scenes.app.channelsbar.welcome": "Добро пожаловать в Twake", "scenes.app.channelsbar.welcoming_message_subtitle": "Станьте профессионалом Twake всего за несколько кликов!", - "scenes.app.mainview.instruction_current_tab": "Начните с выбора канала слева.", - "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "У вас нет разъёма, который может подключиться к каналу.", + "scenes.app.mainview.instruction_current_tab": "Начните с выбора канала в левой части экрана.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "У вас нет расширения, которое может подключиться к каналу.", "scenes.app.mainview.tabs.rename": "Переименовать", - "scenes.app.mainview.tabs.searching_connectors": "Поиск разъёмов...", - "scenes.app.popup.adduser.adresses_message": "Пожалуйста, разделите адреса запятой. Помните, что Twake может ограничить количество приглашений в зависимости от вашей подписки.", + "scenes.app.mainview.tabs.searching_connectors": "Поиск расширений...", + "scenes.app.popup.adduser.adresses_message": "Пожалуйста, разделите адреса запятой или пробелом. Помните, что Twake может ограничить количество приглашений в зависимости от вашей подписки.", "scenes.app.popup.appsparameters.pages._app_identity": "Идентификация приложения", "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Проверьте внешний вид ваших сообщений Twacode", - "scenes.app.popup.appsparameters.pages.alert_published_app": "Проверьте внешний вид ваших сообщений Twacode.", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Ваше приложение опубликовано, вы больше не можете его редактировать.", "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Используйте * в разработке, чтобы разрешить все IP-адреса.", "scenes.app.popup.appsparameters.pages.amazing_app_name": "Мое удивительное приложение", "scenes.app.popup.appsparameters.pages.api_data_description": "Полезные данные для Twake API.", "scenes.app.popup.appsparameters.pages.api_parameters_label": "Настройки API", "scenes.app.popup.appsparameters.pages.app_name_label": "Название приложения", "scenes.app.popup.appsparameters.pages.app_modification_right": "Все менеджеры этой компании смогут редактировать это приложение.", - "scenes.app.popup.appsparameters.pages.app_privileges_information": "Определите, что ваше приложение может редактировать и читать.", - "scenes.app.popup.appsparameters.pages.app_privileges_label": "Привилегии приложени", - "scenes.app.popup.appsparameters.pages.app_update": "Обновить приложение {{$1}} (это приложение использовано {{$2}} раз(а).)", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Определите, доступ к каким данным для просмотра и изменений имеет ваше приложение.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Преимущества приложения", + "scenes.app.popup.appsparameters.pages.app_update": "Обновить приложение {{$1}} (это приложение использовано {{$2}} раз(а))", "scenes.app.popup.appsparameters.pages.application_title": "Приложение", - "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Создавайте и администрируйте свои приложения и разъёмы.", - "scenes.app.popup.appsparameters.pages.apps_title": "Ваши апплликации и разъёмы", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Управляйте своими приложениями и расширениями.", + "scenes.app.popup.appsparameters.pages.apps_title": "Ваши приложения и расширения", "scenes.app.popup.appsparameters.pages.automatique_label": "Автоматически", - "scenes.app.popup.appsparameters.pages.automatique_option_information": "Если Вы активируете 'Автоматически', то это приложение будет автоматически добавлено к следующим рабочим пространствам этой компании", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "Если Вы активируете 'Автоматически', то это приложение будет автоматически добавлено к следующим рабочим средам этой компании.", "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "Разрешенные IP-адреса", "scenes.app.popup.appsparameters.pages.available_publication_alert": "Публикация вашей заявки в настоящее время ожидает подтверждения командами Twake.", "scenes.app.popup.appsparameters.pages.button_force": "Применить принудительно по всей компании", - "scenes.app.popup.appsparameters.pages.call_event_handlers": "Событие типа '{{$1}}' и id '{{$2}}' с пассивами '{{$3}}'.", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "Событие типа '{{$1}}' и идентификатор '{{$2}}' с пассивами '{{$3}}'", "scenes.app.popup.appsparameters.pages.company_label": "Владелец компании", "scenes.app.popup.appsparameters.pages.configuration_label": "Конфигурация", "scenes.app.popup.appsparameters.pages.create_app_button": "Создать приложение", "scenes.app.popup.appsparameters.pages.create_my_app": "Создать мое приложение", - "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Вы еще не создали приложение. Прежде чем создавать приложение или разъём, убедитесь, что его еще нет на нашем рынке приложений.", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Вы еще не создали приложение. Прежде чем создавать приложение или расширение, убедитесь, что его еще нет на нашем рынке приложений.", "scenes.app.popup.appsparameters.pages.danger_zone_description": "Удалить приложение", "scenes.app.popup.appsparameters.pages.danger_zone_label": "Опасная зона", "scenes.app.popup.appsparameters.pages.description_label": "Описание", "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Приложения, разработанные компанией", - "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Позволяет определить, где будет видно ваше приложение.", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Позволяет определить, где будет видимо ваше приложение.", "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Отображать настройки", "scenes.app.popup.appsparameters.pages.error_check_needed": "Произошла ошибка, проверьте ваши данные.", "scenes.app.popup.appsparameters.pages.error_message": "Это имя уже используется другим приложением, пожалуйста, выберите другое.", "scenes.app.popup.appsparameters.pages.error_user_code": "ошибка", "scenes.app.popup.appsparameters.pages.event_subtitle": "События", - "scenes.app.popup.appsparameters.pages.filter_information": "Этот фильтр ограничивает использование вашего API ключа только серверами в вашем коннекторе.", + "scenes.app.popup.appsparameters.pages.filter_information": "Этот фильтр ограничивает использование вашего API ключа только серверами вашего расширения.", "scenes.app.popup.appsparameters.pages.go_back": "Назад", "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Это имя уже используется другим приложением, пожалуйста, выберите другое.", "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "Упрощенное имя", @@ -348,7 +348,7 @@ "scenes.app.popup.appsparameters.pages.interne_availability_application": "Внутреннее приложение", "scenes.app.popup.appsparameters.pages.json_configuration_information": "Перейдите в документацию, чтобы сгенерировать вашу конфигурацию в формате JSON.", "scenes.app.popup.appsparameters.pages.loading": "Загрузка...", - "scenes.app.popup.appsparameters.pages.message_data_next_event": "Пассивные данные, которые будут отправлены в следующем событии", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Пассивные данные, которые будут отправлены во время следующего события", "scenes.app.popup.appsparameters.pages.modify_public_data": "Редактируйте публичные данные вашего приложения.", "scenes.app.popup.appsparameters.pages.new_app_title": "Новое приложение", "scenes.app.popup.appsparameters.pages.ok_user_code": "ок", @@ -358,11 +358,11 @@ "scenes.app.popup.appsparameters.pages.public_login_label": "Публичный идентификатор", "scenes.app.popup.appsparameters.pages.publication_description": "Определите видимость вашего приложения.", "scenes.app.popup.appsparameters.pages.publication_label": "Публикация", - "scenes.app.popup.appsparameters.pages.publish_app_label": "Публикавать приложение", - "scenes.app.popup.appsparameters.pages.read_privileges_label": "Права на чтение", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Опубликавать приложение", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Права на просмотр", "scenes.app.popup.appsparameters.pages.remove_app": "Удалить приложение {{$1}} навсегда.", "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Удалить из всей компании", - "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Удалить из рабочего пространства", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Удалить из рабочей среды", "scenes.app.popup.appsparameters.pages.show_button": "Показать", "scenes.app.popup.appsparameters.pages.status_tilte": "Статус", "scenes.app.popup.appsparameters.pages.string_information": "Эта строка идентифицирует ваше приложение и будет использоваться в командах.", @@ -373,37 +373,37 @@ "scenes.app.popup.appsparameters.pages.write_privileges_label": "Права на редактирование", "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Вы не можете удалить это приложение, если оно опубликовано.", "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Упрощенное название вашего приложения уже используется другим приложением, пожалуйста, измените его.", - "scenes.app.popup.appsparameters.pages.error_app_update_message": "Ошибка произошла при обновлении приложения.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "При обновлении приложения произошла ошибка.", "scenes.app.popup.appsparameters.pages.remove_app_button": "Удалить приложение", "scenes.app.popup.appsparameters.pages.update_button": "Обновить", "scenes.app.popup.createworkspacepage.add_subtitle": "Нужно больше места?", - "scenes.app.popup.createworkspacepage.create_new_workspace": "Создать новое рабочее пространство", - "scenes.app.popup.createworkspacepage.placeholder_name": "Название рабочего пространства", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Создать новую рабочую среду", + "scenes.app.popup.createworkspacepage.placeholder_name": "Название рабочей среды", "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Установить частоту мобильных уведомлений.", "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Частота уведомлений", "scenes.app.popup.userparameter.pages.keywords_notif_description": "Выделите следующие ключевые слова:", "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "Установите частоту уведомлений по электронной почте.", - "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Выберите период, в течение которого Вы не будете получать уведомления.", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Выберите период, в течение которого вы не будете получать уведомления.", "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "Не беспокоить ночью", "scenes.app.popup.userparameter.pages.notif_content_label": "Содержимое уведомлений", "scenes.app.mainview.quick_search_placeholder": "Быстрый поиск", - "scenes.app.popup.userparameter.personnal_workspaces_title": "Ваши рабочие пространства", - "scenes.app.popup.workspaceparameter.admin_current_status": "Вы Администратор.", - "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Вы директор и менеджер компании.", - "scenes.app.popup.workspaceparameter.manager_current_status": "Вы менеджер компании.", - "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Удалить рабочее пространство", - "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Чтобы подтвердить, что вы хотите удалить эту рабочую область, пожалуйста, введите имя ниже и нажмите кнопку \"Удалить\".", - "scenes.app.popup.workspaceparameter.pages.enter": "Введите ", - "scenes.app.popup.workspaceparameter.pages.access_apps": "Доступ к вашим приложениям и разъёмам", - "scenes.app.popup.workspaceparameter.pages.moderator_status": "Администратор", - "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Вы не можете покинуть рабочее пространство, потому что вы последний администратор. Вы можете определить нового администратора или удалить/архивировать это рабочее пространство.", + "scenes.app.popup.userparameter.personnal_workspaces_title": "Ваши рабочие среды", + "scenes.app.popup.workspaceparameter.admin_current_status": "Вы являетесь администратором.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Вы являетесь администратором рабочей среды.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Вы являетесь администратором компании.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Удалить рабочую среду", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Удаление рабочей среды нельзя отменить. Все сообщения и файлы не смогут быть восстановлены.", + "scenes.app.popup.workspaceparameter.pages.enter": "Ввести ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Доступ к вашим приложениям и расширениям", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Администратор рабочей среды", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Вы не можете покинуть рабочую среду, потому что вы последний администратор. Вы можете определить нового администратора или удалить/архивировать эту рабочую среду.", "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Все приложения", "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Приложения вашей компании", "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Интеграции", "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Поиск приложений", - "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Приложения этого рабочего пространства", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Приложения этой рабочей среды", "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Вернуться к поиску", - "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Добавить сотрудников", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Пригласить пользователей", "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Сотрудники", "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Приложения, разработанные компанией", "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Идентификация компании", @@ -415,29 +415,29 @@ "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Приложения, разработанные компанией", "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Параметры отображения", "scenes.app.popup.workspaceparameter.pages.install_button": "Установить", - "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Установить приложение в этом рабочем пространстве.", - "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Приложения, установленные в этом рабочем пространстве {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Установить приложение в этой рабочей среде.", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Приложения, установленные в этой рабочей среде {{$1}}", "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Приложения, установленные в других областях компании {{$1}}", "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Установленные приложения", - "scenes.app.popup.workspaceparameter.pages.invitation_error": "Ошибка произошла при приглашении следующих людей: ", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Произошла ошибка при приглашении следующих людей: ", "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Убедитесь, что используемое имя пользователя или электронная почта действительны.", - "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Редактировать изображения этого рабочего пространства", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Редактировать изображения этой рабочей среды", "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Логотип", - "scenes.app.popup.workspaceparameter.pages.name_description": "Изменить название этого рабочего пространства", - "scenes.app.popup.workspaceparameter.pages.name_label": "Название рабочего пространства", + "scenes.app.popup.workspaceparameter.pages.name_description": "Изменить название этой рабочей среды", + "scenes.app.popup.workspaceparameter.pages.name_label": "Название рабочей среды", "scenes.app.popup.workspaceparameter.pages.no_access": "Нет доступа.", - "scenes.app.popup.workspaceparameter.pages.no_app_information": "У вас нет приложений в этом рабочем пространстве", - "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Покинуть это рабочее пространство", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "У вас нет приложений в этой рабочей среде", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Покинуть эту рабочую среду", "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Доступ с правом чтения", "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Удалить из всей компании", - "scenes.app.popup.workspaceparameter.pages.research_by": "Поиск приложений по названию и разъёмам", + "scenes.app.popup.workspaceparameter.pages.research_by": "Поиск приложений по названию и категории", "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Поиск приложений...", "scenes.app.popup.workspaceparameter.pages.show_button": "Показать", - "scenes.app.popup.workspaceparameter.pages.title": "Настройки рабочего пространства", + "scenes.app.popup.workspaceparameter.pages.title": "Настройки рабочей среды", "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Доступ к webhooks", "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Максимальный вес 5 мб.", - "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Удалить из этого рабочего пространста", - "scenes.app.popup.workspaceparameter.pages.worspace_notif": "рабочее пространство", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Удалить из этой рабочей среды", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "рабочая среда", "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Права на редактирование", "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Ваши приложения", "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Платежи и подписки", @@ -445,8 +445,8 @@ "scenes.app.workspacesbar.components.create_company_menu": "Создать компанию", "scenes.app.workspacesbar.components.grp_parameters": "Настройки {{$1}}", "scenes.apps.calendar.add_calendar_menu": "Добавить календарь", - "scenes.apps.calendar.connectors_menu": "Разъёмы...", - "scenes.apps.calendar.connectors_search_menu": "Поиск разъёмов...", + "scenes.apps.calendar.connectors_menu": "Расширения...", + "scenes.apps.calendar.connectors_search_menu": "Поиск расширений...", "scenes.apps.calendar.create_calendar_title": "Создать календарь", "scenes.apps.calendar.day_option": "День", "scenes.apps.calendar.edit_calendar_title": "Редактировать календарь", @@ -473,17 +473,17 @@ "scenes.apps.calendar.my_calendar": "Мой календарь", "scenes.apps.calendar.my_calendar_label": "Мой календарь", "scenes.apps.calendar.my_calendar_menu": "Мой календарь", - "scenes.apps.calendar.no_calendar_text": "Вы не установили никаких календарей для этого рабочего пространства.", - "scenes.apps.calendar.no_connectors_menu_text": "У вас нет разъемов, которые могут подключаться к календарю.", - "scenes.apps.calendar.remove_calendar_confirmation": "Удалить календарь и его события навсегда?", + "scenes.apps.calendar.no_calendar_text": "Вы не установили никаких календарей для этой рабочей среды.", + "scenes.apps.calendar.no_connectors_menu_text": "У вас нет расширений, которые могут подключаться к календарю.", + "scenes.apps.calendar.remove_calendar_confirmation": "Удалить календарь и события из него навсегда?", "scenes.apps.calendar.today_menu": "Сегодня", "scenes.apps.calendar.week_option": "Неделя", - "scenes.apps.calendar.workspace": "Рабочее пространство", - "scenes.apps.calendar.workspace_label": "Это рабочее пространство", - "scenes.apps.calendar.workspace_menu": "Рабочее пространство", + "scenes.apps.calendar.workspace": "Рабочая среда", + "scenes.apps.calendar.workspace_label": "Эта рабочая среда", + "scenes.apps.calendar.workspace_menu": "Рабочая среда", "scenes.apps.drive.add_button": "Добавить", - "scenes.apps.drive.message_added_file": "{{$1}} послал {{$2}}.", - "scenes.apps.drive.message_added_file_no_name": "{{$1}} послал файл.", + "scenes.apps.drive.message_added_file": "{{$1}} отправил {{$2}}.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} отправил файл.", "scenes.apps.drive.choose_folder_button": "Выбрать каталог", "scenes.apps.drive.choose_file_button": "Выбрать файл", "scenes.apps.drive.create_folder_button": "Создать", @@ -503,15 +503,15 @@ "scenes.apps.drive.no_storage_app_alert": "У вас нет приложения, позволяющего добавлять внешнее хранилище.", "scenes.apps.drive.remove_definitely_menu": "Удалить навсегда", "scenes.apps.drive.restore_menu": "Восстановить", - "scenes.apps.drive.throw_menu": "Выкидывать в корзину", - "scenes.apps.drive.trash_empty_menu": "Опорожнять корзину", + "scenes.apps.drive.throw_menu": "Переместить в корзину", + "scenes.apps.drive.trash_empty_menu": "Очистить корзину", "scenes.apps.drive.unconfigured_tab": "Эта вкладка еще не настроена.", "scenes.apps.drive.viewer.edit_with_button": "Отредактировать с помощью {{$1}}", "scenes.apps.drive.viewer.loading_preview_message": "Загрузка...", - "scenes.apps.drive.viewer.no_preview_message": "Не могу показать такой тип файла.", - "scenes.apps.drive.viewer.open_with_button": "Открыть с...", + "scenes.apps.drive.viewer.no_preview_message": "Нельзя открыть этот тип файла.", + "scenes.apps.drive.viewer.open_with_button": "Открыть с помощью...", "scenes.apps.messages.input.placeholder": "Написать сообщение. Используйте @ для упоминания определенного пользователя.", - "scenes.apps.messages.just_you": "Видимый только вам", + "scenes.apps.messages.just_you": "Видимо только вам", "scenes.apps.messages.message.new_messages_bar": "Новые сообщения", "scenes.apps.messages.message.cancel_button": "Отменить", "scenes.apps.messages.message.modify_button": "Редактировать", @@ -523,28 +523,28 @@ "scenes.apps.messages.message.show_responses_button": "Просмотр всех ответов", "scenes.apps.messages.message.types.first_channel_message_text": "Это первое сообщение канала", "scenes.apps.messages.message.types.first_message_text": "Это первое сообщение", - "scenes.apps.messages.messageslist.get_writing_user": "пишет...", - "scenes.apps.messages.messageslist.get_writing_users": "пишут...", + "scenes.apps.messages.messageslist.get_writing_user": "печатает...", + "scenes.apps.messages.messageslist.get_writing_users": "печатают...", "scenes.apps.messages.messageslist.go_last_message_button": "Перейти к последнему сообщению", "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Новые сообщения", - "scenes.error_on_twake": "“Хьюстон у нас проблема“", - "scenes.help_us": "Однако, если вы хотите помочь нам исправить эту ошибку, отправьте нам сообщение ниже:", + "scenes.error_on_twake": "“Хьюстон, у нас проблема“", + "scenes.help_us": "Если вы хотите помочь нам исправить эту ошибку, отправьте сообщение ниже: ", "scenes.login.verifymail.alert": "Мы проверяем вашу электронную почту!", "scenes.login.verifymail.error_message": "Произошла ошибка", "scenes.login.verifymail.signin_button": "Вход", - "scenes.login.verifymail.success": "Ваша электронная почта была успешно проверена!", - "scenes.login.verifymail.verification_waiting": "Ожидание проверки...", - "scenes.no_panic": "Не паникуйте, просто перезагрузите эту страницу, чтобы найти Twake.", + "scenes.login.verifymail.success": "Ваша электронная почта была успешно подтверждена!", + "scenes.login.verifymail.verification_waiting": "Ожидание подтверждения...", + "scenes.no_panic": "Без паники! Просто перезагрузите данную страницу, чтобы починить Twake.", "services.apps.calendar.deadline_icon": "Крайний срок", "services.apps.calendar.event_icon": "Cобытие", - "services.apps.calendar.move_icon": "Путешествие", + "services.apps.calendar.move_icon": "Перенести", "services.apps.calendar.reminder_icon": "Напоминание", "services.apps.messages.no_app": "Этого приложения не существует.", "services.apps.messages.no_command_possible": "Мы не можем выполнить команду '{{$1}}', потому что '{{$2}}' не существует или не позволяет создавать команды.", "services.user.notification_parameters_update_alert": "Настройки уведомлений были обновлены.", "services.user.update_password_alert": "Ваш пароль был обновлен.", "scenes.app.workspaces.components.skip": "Пропустить", - "scenes.apps.calendar.unconfigured_tab": "Эта закладка еще не настроена.", + "scenes.apps.calendar.unconfigured_tab": "Эта вкладка еще не настроена.", "scenes.apps.drive.trash": "Корзина", "scenes.apps.drive.top_menu_more": "Больше", "scenes.apps.drive.top_menu_no_items": "{{$1}} элементы", @@ -566,37 +566,37 @@ "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "Отменить приглашение", "scenes.apps.account.account.fullname": "Полное имя", "login.email_login": "Электронная почта / Логин", - "scenes.apps.account.account.password_for_user": "Пароль для вашего пользователя", - "scenes.apps.account.account.send_info": "Отправьте эту информацию вашему сотруднику, чтобы он получил новые учетные данные.", + "scenes.apps.account.account.password_for_user": "Пароль пользователя", + "scenes.apps.account.account.send_info": "Отправьте данную информацию вашему сотруднику, чтобы он получил новые учетные данные.", "scenes.apps.account.account.save": "Сохранить аккаунт", - "scenes.apps.account.message_temporary": "Временный счет работает как обычный Twake, но вы генерируете его пароль и при необходимости можете его сбросить.", + "scenes.apps.account.message_temporary": "Временный аккаунт работает как обычный аккаунт Twake, но вы генерируете пароль к нему и при необходимости можете его сбросить.", "scenes.apps.account.message_user_signin": "Ваш пользователь может войти в систему в любое время, используя эту же почту, и сменить временный аккаунт на обычный.", - "scenes.app.mainview.link_expired": "Эта публичная ссылка недействительна или ее срок действия истек.", - "scenes.app.mainview.create_account": "Создайте свое рабочее пространство бесплатно в ", + "scenes.app.mainview.link_expired": "Эта публичная ссылка недействительна или срок ее действия истек.", + "scenes.app.mainview.create_account": "Создайте свою рабочую среду бесплатно в ", "scenes.apps.calendar.modals.reminder_add": "Добавить напоминание", "scenes.apps.parameters.workspace_sections.members.invite_all": "Пригласить всех", - "scenes.app.taskpicker.select": "Выберите", + "scenes.app.taskpicker.select": "Выбрать", "components.listmanager.filter": "Фильтр", - "scenes.apps.tasks.no_connector": "Нет разъёма", + "scenes.apps.tasks.no_connector": "Нет расширения", "components.attachmentpicker.add_attachment": "Добавить вложения", "components.input.copied": "Скопировано", "components.drive.new_versions": "Добавить новую версию", "components.drive.navigators.directory_not_found": "Каталог не найден.", - "components.drive.right_preview.suppress_link": "Подавить ссылку", + "components.drive.right_preview.suppress_link": "Скрыть ссылку", "components.drive.right_preview.create_link": "Создать ссылку доступа", "components.drive.moove_here": "Переместить сюда", "components.drive.modify_uslist": "Изменить список пользователей", "components.tagpicker.tag_name": "Название метки", - "components.upload.drop_files": "Перетащите сюда свои файлы", - "components.workspace.list_manager.no_workspace": "Нет рабочего пространства", - "components.workspace.list_manager.add": "Добавить рабочие пространства", - "components.workspace.list_manager.current_space": "Текущая рабочая область", + "components.upload.drop_files": "Перетащить файлы сюда", + "components.workspace.list_manager.no_workspace": "Нет рабочей среды", + "components.workspace.list_manager.add": "Добавить рабочие среды", + "components.workspace.list_manager.current_space": "Текущая рабочая среда", "components.workspace.list_manager.current_company": "Текущая компания", "components.workspace.list_manager.all": "Все", "components.workspace.calendar.invalid": "Недействительны", "components.searchpopup.enter_text": "Введите текст для поиска в Twake.", "components.searchpopup.loading": "Загрузка дополнительных результатов", - "components.searchpopup.filter_ws": "Фильтровать рабочие пространства", + "components.searchpopup.filter_ws": "Фильтровать рабочие среды", "components.searchpopup.tags": "Метки", "components.searchpopup.size": "Размер", "components.searchpopup.creation": "Создание", @@ -606,17 +606,17 @@ "components.searchpopup.mentions": "Упоминания", "components.searchpopup.only_pinned": "Только закрепленные сообщения", "components.alert.confirm": "Подтвердите ваше действие", - "components.alert.confirm_click": "Подтвердите ваше действие, нажав на кнопку Подтвердить.", + "components.alert.confirm_click": "Подтвердите ваше действие, нажав на кнопку \"Подтвердить\".", "components.searchpopup.tasks": "Задачи", "scenes.app.mainview.advanced_search_placeholder": "Расширенный поиск", - "components.searchpopup.hide_filters": "скрыть", - "components.searchpopup.show_filters": "фильтры", + "components.searchpopup.hide_filters": "скрыть фильтры", + "components.searchpopup.show_filters": "показать фильтры", "components.searchpopup.load_more": "Загрузить больше результатов", "general.more": "Больше", - "scenes.apps.board.archived_tasks": "Архивные задачи ({{$1}})", + "scenes.apps.board.archived_tasks": "Заархивированные задачи ({{$1}})", "scenes.apps.board.active_tasks": "Активные задачи", "scenes.apps.board.kanban": "Канбан", - "scenes.apps.board.display_as": "Показать как", + "scenes.apps.board.display_as": "Отобразить как", "scenes.apps.board.new_task": "+ Новая задача", "scenes.apps.board.all_boards": "Все доски", "components.userlistmanager.no_users": "Нет пользователей.", @@ -635,32 +635,32 @@ "components.calendar.calendarselector.from": "C", "scenes.apps.drive.move_text2": "Переместить", "components.attachmentpicker.from_computer": "С компьютера", - "components.attachmentpicker.from_twake": "Из Twake Документы", + "components.attachmentpicker.from_twake": "Из Twake Documents", "components.attachmentpicker.file": "Файл", - "components.attachmentpicker.remove_attach": "Снять вложение", - "scenes.apps.drive.remove_attachs": "Снять вложения", + "components.attachmentpicker.remove_attach": "Удалить вложение", + "scenes.apps.drive.remove_attachs": "Удалить вложения", "components.drive.elements.see": "Посмотреть", "components.drive.elements.current_name": "Текущее название : ", - "scenes.apps.drive.right_preview.public": "Открыть доступ", + "scenes.apps.drive.right_preview.public": "Открытый доступ", "components.drive.elements.configurate_mod": "Настройка модуля...", "components.drive.elements.manage_version": "Управление версиями", - "scenes.app.popup.createcompany.try_again": "Пожалуйста повторите.", + "scenes.app.popup.createcompany.try_again": "Пожалуйста повторите попытку.", "scenes.app.popup.workspace.edit_temp": "Редактировать временный аккаунт", "scenes.app.popup.workspace.create_temp": "Создать временный аккаунт", "scenes.apps.tasks.active_tasks": "активные(х) задачи(ь)", "scenes.apps.drive.right_preview.versions": "Версии", - "components.locked_features.locked_workspace_popup.title": "Вы не можете создать больше рабочего пространства", - "components.locked_features.locked_workspace_popup.subtitle": "В бесплатной версии у вас может быть только 1 рабочее место в вашей компании.", - "components.locked_features.locked_workspace_popup.text": "Упс !! Похоже, вы хотите создать новое рабочее место в своей компании. Возможно, вы захотите обновить свой план, если хотите сотрудничать в нескольких рабочих областях. Изучите наши варианты цен и выберите лучший вариант для совместной работы вашей команды.", + "components.locked_features.locked_workspace_popup.title": "Вы не можете создать больше рабочих сред", + "components.locked_features.locked_workspace_popup.subtitle": "В бесплатной версии у вас может быть только 1 рабочая среда в компании.", + "components.locked_features.locked_workspace_popup.text": "Ой... Похоже, вы хотите создать новую рабочую среду в своей компании. Вам необходимо обновить свой план. Изучите наше ценовое предложение и выберите лучший вариант для совместной работы вашей команды.", "components.locked_features.locked_only_office_popup.title": "Вы не можете редактировать этот файл", "components.locked_features.locked_only_office_popup.subtitle": "В бесплатной версии вы не можете использовать onlyoffice.", - "components.locked_features.locked_only_office_popup.text": "Упс !! Похоже, вы хотите отредактировать файл из Twake. Возможно, вы захотите подумать об обновлении своего плана, если хотите сотрудничать с офисными файлами. Изучите наши варианты цен и выберите лучший вариант для совместной работы вашей команды.", + "components.locked_features.locked_only_office_popup.text": "Ой... Похоже, вы хотите отредактировать файл из Twake. Вам необходимо обновить свой план, чтобы совместно использовать файлы. Изучите наше ценовое предложение и выберите лучший вариант для совместной работы вашей команды.", "components.locked_features.locked_drive_popup.title": "Вы не можете загружать больше файлов", "components.locked_features.locked_drive_popup.subtitle": "В бесплатной версии можно хранить только 6 ГБ.", - "scenes.app.integrations_parameters.title" :"Интеграции", + "scenes.app.integrations_parameters.title": "Интеграции", "scenes.app.integrations_parameters.applications_table.name": "Имя", "scenes.app.integrations_parameters.applications_table.title": "Другие интеграции", - "scenes.app.integrations_parameters.applications_table.search_placeholder" : "Приложение для поиска", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Приложение для поиска", "scenes.app.integrations_parameters.company_application_popup.tag": "Установлены", "scenes.app.integrations_parameters.company_application_popup.btn": "Установить", "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Информация", @@ -669,10 +669,242 @@ "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Дата создания", "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Версия", "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Показать", - "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application" : "Удалить из компании", - "scenes.app.integrations_parameters.company_applications_table.name" : "Имя", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Удалить из компании", + "scenes.app.integrations_parameters.company_applications_table.name": "Имя", "scenes.app.integrations_parameters.company_applications_table.title": "Установлен в вашей компании", - "app.state.recoil.hooks.use_current_company_applications.toaster_delete" : "Успешно удалил {{$1}} из вашей компании", - "app.state.recoil.hooks.use_current_company_applications.toaster_add" : "{{$1}} успешно добавлен в вашу компанию", - "scenes.apps.messages.input.replied_to" : "ответил " -} \ No newline at end of file + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Введите минимум три символа для отображения пользователей", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Пользователь не найден", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Не найдено ни одного эмодзи", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Команда не найдена", + "general.retry": "Повторить попытку", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Пригласительная ссылка для рабочей среды", + "application.load.longer": "Сервер не отвечает слишком долго, пожалуйста, ожидайте или обновите страницу...", + "scenes.apps.account.notifications.sound": "Звуковые уведомления", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Количество сообщений", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "В бесплатной версии Twake вы можете получить доступ лишь к {{$1}} последним сообщениям.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Больше планов", + "scenes.apps.messages.input.hide_formatting": "Скрыть форматирование", + "scenes.apps.messages.input.show_formatting": "Отобразить форматирование", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Информация, связанная с управлением приложениями", + "components.newversion.new_version_modal.title": "Доступно новое обновление !", + "scenes.apps.drive.download_all_button": "Скачать все", + "components.inputs.input_with_select.input.placeholder": "Название канала", + "components.inputs.input_with_select.select.placeholder": "Название раздела", + "components.inputs.input_with_select.select.no_sections": "Здесь вы можете группировать свои каналы", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} удалил {{$2}} из канала", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} изменил описание", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} переименовал канал в {{$2}}", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} добавил новую вкладку {{$2}} {{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} удалил вкладку {{$2}} {{$3}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} добавил новое расширение {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} удалил расширение {{$2}}", + "components.alert.leave_private_channel.description": "Вы не сможете снова присоединиться к этому частному каналу, если вас никто не пригласит.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Ты не являетесь членом", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Загрузить больше", + "components.unverified_account.typography_text_danger": "Пожалуйста, подтвердите свою учетную запись в течение {{$1}} дней. В противном случае учетная запись будет заблокирована через 7 дней и окончательно удалена через 30 дней. Вы можете подтвердить свою учетную запись с помощью электронного письма с подтверждением.", + "components.unverified_account.verification_details": "Мы отправили электронное письмо с подтверждением по адресу", + "components.account_verification_status_sentence": "Статус вашей учетной записи: {{$1}}", + "components.account_verication_status_unverified": "Проверка не пройдена", + "components.account_verication_status_blocked": "Заблокирован", + "components.unverified_account.re_send_email": "Не получили письмо?", + "components.add_mails_workspace.title_2": "Twake - это инструмент для совместной работы в команде, поэтому мы советуем пригласить других пользователей, чтобы протестировать созданную для вас рабочую среду.", + "components.add_mails_workspace.text_area_placeholder": "Введите адреса электронной почты пользователей*", + "components.verify_mail.title_2": "Теперь вы являетесь официальным пользователем Twake!", + "services.console_services.toaster.success_verify_email": "Ссылка для подтверждения была отправлена по вашему адресу электронной почты", + "scenes.app.popup.workspaceparameter.edit_from_console": "См. в \"Консоли\"", + "services.console_services.toaster.success_invite_emails": "Успешно добавлен(о) {{$1}} пользователь(ей)", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Поиск гостей или ожидающих писем", + "scenes.client.channels_bar.modals.guest_management.tips": "Добавьте или найдите электронную почту, используя введенные выше данные", + "general.user.role.company.guest": "Гость", + "general.user.deleted": "Удаленная учетная запись", + "components.richtexteditor.toolbar.underline": "Подчеркнутый", + "components.richtexteditor.toolbar.italic": "Курсив", + "components.richtexteditor.toolbar.ordered-list": "Заказанный список", + "components.richtexteditor.toolbar.code-block": "Блок кода", + "components.locked_features.locked_history_banner.title": "Вы достигли лимита сообщений", + "components.locked_features.locked_history_banner.description": "У вашей компании много сообщений! Обновите сейчас, чтобы получить доступ ко всей истории сообщений.", + "components.locked_features.locked_history_banner.button": "Узнать больше", + "components.locked_features.locked_guests_popup.title": "Функция гостей заблокирована", + "components.locked_features.locked_guests_popup.subtitle": "Эта функция недоступна в бесплатной версии Twake", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Возникла проблема с подпиской вашей компании. Пожалуйста, изучите ваш", + "components.on_boarding.company_billing_banner.link": "план подписки компании", + "components.on_boarding.popups.blocked_company.title": "Ваша компания заблокирована из-за проблемы с оплатой", + "components.on_boarding.popups.blocked_company.description": "Срок действия вашей подписки на Twake истек. Пожалуйста, свяжитесь с владельцем или администратором вашей компании, чтобы продлить подписку и снова иметь возможность общаться с командой!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Хотите узнать больше о плане подписки для компаний?", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Кликните сюда", + "components.on_boarding.popups.blocked_company.or": "Или", + "components.on_boarding.popups.blocked_company.company_selector": "Перейти в другую компанию", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Вы не можете прикрепить более {{$2}} файлов к сообщению", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} удалил свое сообщение", + "components.member.user_parts.and_more_user_text": " и еще {{$1}} пользователей", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Создайте частный канал", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " вместо", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "Вы не можете добавить более 10 пользователей", + "general.uploading": "Загрузка", + "components.upload.drop_files.toaster.error": "Вы не можете загрузить более {{$1}} файлов", + "components.emoji_picker.categories.frequently_used": "Часто используемые", + "components.emoji_picker.categories.smileys_and_people": "Смайлики и люди", + "components.emoji_picker.categories.animals_and_nature": "Животные и природа", + "components.emoji_picker.categories.food_and_drink": "Еда и напитки", + "components.emoji_picker.categories.travel_and_places": "Путешествия и места", + "components.emoji_picker.categories.objects": "Объекты", + "components.emoji_picker.categories.symbols": "Символы", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "Роль", + "general.email": "Эл. адрес", + "scenes.join.join_workspace_from_company": "Присоединяйтесь к {{$1}} с {{$2}}!", + "scenes.join.twake_description": "Twake - это цифровая рабочая среда с открытым исходным кодом, созданная для повышения продуктивности вашей команды", + "scenes.join.login_first_button": "Войти или создать учетную запись", + "scenes.join.join_the_team_button": "Присоединиться к команде", + "general.verify": "Проверить", + "components.inputs.input_with_select.button.tooltip": "Установить раздел канала", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Создана новая ссылка", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Успешно скопировано в буфер обмена", + "scenes.app.popup.adduser.magiclinks.action_copy": "Копировать", + "scenes.app.popup.adduser.magiclinks.action_generate": "Сгенерировать", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Вы должны быть единственным участником рабочей среды, чтобы удалить ее. Удалите прочих участников и попробуйте еще раз.", + "scenes.apps.messages.input.emoji": "Эмодзи", + "components.verify_mail.title_1": "Поздравляем", + "components.verify_mail.text": "Прежде всего, вы должны подтвердить свой адрес электронной почты. Мы отправили ссылку для подтверждения по адресу", + "components.verify_mail.paragraph": "Вы можете сделать это позже, но непроверенные учетные записи имеют доступ только к ограниченной версии Twake", + "services.console_services.toaster.add_email_error_message": "Ошибка при добавлении {{$1}}", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Письмо отправлено", + "general.user.role.company.admin": "Администратор компании", + "components.richtexteditor.toolbar.strikethrough": "Зачеркнутый", + "components.richtexteditor.toolbar.code": "Код", + "components.richtexteditor.toolbar.unordered-list": "Маркированный список", + "components.locked_features.locked_guests_popup.description": "Ой... Похоже, вы хотите пригласить внешних пользователей в свою рабочую среду. Вам необходимо обновить свой план, чтобы сотрудничать с гостями и внешними партнерами. Изучите наше ценовое предложение и выберите лучший вариант для совместной работы вашей команды.", + "components.locked_features.locked_guests_popup.learn_more_button": "Узнать больше", + "components.locked_features.locked_guests_popup.or": "Или", + "scenes.apps.messages.input.attach_file.from_computer": "С компьютера", + "scenes.client.main_view.main_header.search_input": "Поиск", + "scenes.apps.drive.new_link_title": "Новая ссылка", + "scenes.apps.drive.default_link_name": "Без названия", + "components.emoji_picker.input_search_placeholder": "Поиск", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Вы удалили это сообщение", + "components.emoji_picker.categories.flags": "Флаги", + "components.emoji_picker.categories.search_result": "Результаты поиска", + "components.emoji_picker.categories.not_found": "Эмодзи не найдены", + "general.resume": "Продолжить", + "general.pause": "Пауза", + "scenes.client.channels_bar.modals.guest_management.title": "Управление гостями в {{$1}}", + "components.channelworkspacelist.title": "Каналы", + "general.user.role.company.member": "Участник", + "components.richtexteditor.toolbar.bold": "Полужирный", + "scenes.client.channelbar.channelmemberslist.tag": "Вы", + "components.alert.leave_private_channel.title": "Вы уверены, что хотите покинуть канал?", + "components.richtexteditor.toolbar.blockquote": "Цитата", + "components.emoji_picker.categories.activity": "Деятельность", + "scenes.apps.messages.input.edited": "Отредактировано", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Отложить", + "scenes.join.loading": "Загрузка…", + "scenes.join.wrong_link_title": "Эта ссылка больше не доступна", + "scenes.join.wrong_link_description": "Попросите человека, который пригласил вас присоединиться к этой компании, выслать новую ссылку или создайте собственную компанию", + "scenes.join.create_the_company_button": "Создать компанию", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} добавил {{$2}} на канал", + "scenes.app.mainview.channel_description": "Опишите канал", + "scenes.apps.messages.message.unpin_button": "Открепить сообщение", + "components.calendar.repetition.on": "На", + "scenes.apps.messages.new_thread": "Начать новое обсуждение", + "scenes.apps.messages.input.send_message": "Отправить сообщение", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Автоматически приглашать всех пользователей рабочей среды на этот канал", + "components.blocked_account.trial_period_over": "Ваш пробный период закончился. Чтобы разблокировать учетную запись и получить доступ ко всем функциям, пожалуйста, подтвердите ее по электронной почте", + "components.add_mails_workspace.button": "Начать использовать Twake", + "components.add_mails_workspace.title_1": "Добавить пользователей", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Показывать содержимое личных сообщений", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Скрыть содержимое личных сообщений", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} отправил несколько файлов.", + "scenes.apps.messages.message.pin_button": "Закрепить сообщение", + "scenes.apps.messages.message.copy_link": "Скопировать ссылку на сообщение", + "scenes.app.popup.appsparameters.pages.icon": "Значок", + "scenes.app.popup.appsparameters.pages.title_informations": "Основная информация", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Текущий идентификатор пользователя", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Текущий идентификатор рабочей среды", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Текущий идентификатор группы", + "scenes.client.channelbar.channelmemberslist.title": "Пользователи в {{$1}}", + "scenes.client.channelbar.channelmemberslist.loader": "Загрузить больше", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Поиск пользователей", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Удалить с канала", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Создать канал", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Присоединиться к каналу", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Поиск канала, пользовательских или личных сообщений", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Создать новую вкладку", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "Переименовать {{$1}}", + "components.connectorslistmanager.add_connectors": "Добавить расширения", + "components.notifications.hidden_notifications_button.children": "Новые сообщения", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "Заявка", + "scenes.client.channelbar.channelmemberslist.no_members": "На этом канале нет пользователей. Вы можете пригласить их, нажав \"Добавить пользователей\".", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Скрыть обсуждение", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} адрес(а) электронной почты будет(ут) добавлен(ы)", + "components.newversion.new_version_component.row.part_1": "Ваша версия Twake устарела", + "components.newversion.new_version_component.row.part_2": "предлагаем вам обновить приложение и попробовать наши новые функции!", + "components.newversion.new_version_component.link": "Нажмите сюда, чтобы обновить", + "general.re_send": "Отправить снова", + "components.verify_mail.button": "Добавить пользователя", + "services.console_services.toaster.add_emails_error": "Ошибка при добавлении адреса(ов) электронной почты", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Возникла проблема с подпиской вашей компании. Обратитесь к владельцу или администратору компании!", + "scenes.apps.tasks.select_user_button": "Просмотр задач для другого пользователя", + "scenes.apps.tasks.select_user": "Поиск пользователя", + "scenes.app.popup.workspaceparameter.pages.table_title": "Имя", + "login.create_account": "Создать учетную запись", + "'": "'", + "login.login_error": "Ошибка при входе в систему", + "\"": "\"", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Успешно удалил {{$1}} из вашей компании", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "{{$1}} успешно добавлен в вашу компанию", + "scenes.apps.messages.input.replied_to": "ответил ", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} пишет...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} и {{$2}} пишут...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} и еще {{$3}} пользователей пишут...", + "scenes.apps.messages.message.types.no_message_in_thread": "Пока никто не ответил.", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Вас еще никто не пригласил в рабочую среду.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Рабочая среда по умолчанию", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Автоматически приглашать всех пользователей рабочей среды на этот канал", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Вы собираетесь удалить {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "У вас все еще есть {{$1}} участников в {{$2}}. Вы должны удалить всех участников, чтобы иметь возможность удалить эту рабочую среду.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Я понимаю, что все сообщения и файлы моей рабочей среды будут удалены.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Максимальный размер логотипа 5 МБ", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Неверный формат, разрешены только форматы png, gif и jpg", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Неизвестная ошибка", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Ошибка", + "scenes.app.channelsbar.currentuser.reset": "Перезагрузить", + "components.locked_features_components.locked_invite_alert.message_part_1": "Ваша компания достигла максимального лимита в {{$1}} участников. Пожалуйста, ", + "components.locked_features_components.locked_invite_alert.message_link": "повысьте статус вашей компании", + "components.locked_features_components.locked_invite_alert.message_part_2": " чтобы пригласить больше участников.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Видеть всех членов моей компании на консоли", + "components.locked_features_components.locked_invite_alert.message_magic_link": " обратитесь к владельцу или администратору вашей компании.", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Приложение {{$1}} успешно удалено!", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Опишите ваше приложение в нескольких словах", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Новая интеграция", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Я понимаю, что владелец и администраторы этой компании смогут изменять и публиковать это приложение.", + "twake.application.access.title": "Выберите правильные области для вашего приложения.", + "twake.application.access.no_default_scopes_available'": "У этой интеграции нет доступа {{$1}}", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "документация по API Twake", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Если вы не знаете, как их заполнить, перейдите на ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Закрытый ключ", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Ошибка при удалении приложения {{$1}}!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Успешная заявка {{$1}}!", + "scenes.app.integrations_parameters.add_application": "Новая интеграция", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Настройки разработчика", + "components.rich_text_editor.plugins.suggestions.loading": "Ищете больше", + "components.open_desktop_popup.subtitle": "открыто в приложении Twake", + "components.open_desktop_popup.open_here_link": "Вместо этого откройте здесь", + "molecules.download_banner.title": "Получите максимум от Twake, загрузите настольное приложение прямо сейчас", + "molecules.download_banner.download_button": "Скачать настольное приложение", + "scenes.app.channelsbar.channel_copy_link": "Скопировать ссылку на канал", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Успешно обновлено", + "components.searchpopup.all": "Все", + "components.searchpopup.no_results_for": "Не найдено результатов для", + "components.searchpopup.try_new_search": "Искать еще раз", + "components.searchpopup.chats": "Чаты", + "components.searchpopup.media": "Медиа", + "components.searchpopup.files": "Файлы", + "components.searchpopup.recent_chats": "Недавние чаты", + "components.searchpopup.recent_media": "Последние медиа", + "components.searchpopup.recent_files": "Последние файлы", + "components.searchpopup.recent_channels_and_contacts": "Последние каналы и контакты", + "components.searchpopup.header_title": "Поиск", + "components.searchpopup.scope.company": "во всей компании", + "components.searchpopup.scope.channel": "на этом канале", + "components.searchpopup.channels": "каналы", + "components.searchpopup.messages": "Сообщения" +} diff --git a/twake/frontend/public/locales/si.json b/twake/frontend/public/locales/si.json index 457eac59ff..6ff5decd3b 100644 --- a/twake/frontend/public/locales/si.json +++ b/twake/frontend/public/locales/si.json @@ -258,7 +258,7 @@ "components.drive.elements.manage_version": "අනුවාද කළමණාකරනය", "scenes.app.popup.workspace.edit_temp": "තාවකාලික ගිණුම සංස්කරණය", "scenes.app.popup.appsparameters.pages.icon": "නිරූපකය", - "scenes.app.popup.appsparameters.pages.smalltext_user_id": "වත්මන් පරිශීලක හැඳු.", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "වත්මන් පරිශීලක හැඳුනුම්පත", "scenes.client.channelbar.channelmemberslist.autocomplete": "පරිශීලකයෙකු සොයන්න හෝ එකතුකරන්න", "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "යෙදුම", "components.newversion.new_version_component.row.part_1": "ඔබ යල් පැන ගිය ට්වේක් අනුවාදයක් ධාවනය කරමින්", @@ -442,11 +442,469 @@ "scenes.apps.drive.new_file_title": "නව ගොනුව", "services.apps.calendar.move_icon": "ගෙනයන්න", "scenes.login.home.create_account": "ගිණුමක් සාදන්න", - "scenes.login.create_account.step_2_subtitle_a": "වෙනත් පරිශීලකයින්ට ඔබව හඳුනා ගැනීමට සම්පූර්ණ නම එකතු කරන්න.", + "scenes.login.create_account.step_2_subtitle_a": "වෙනත් පරිශීලකයින්ට හඳුනා ගැනීමට සම්පූර්ණ නම එකතු කරන්න.", "scenes.app.workspaces.create_company.invitations.title_2": "කණ්ඩායමට පරිශීලකයින් එකතු කරන්න.", "scenes.app.workspaces.welcome_page.add_secondary_emails": "ද්විතීයික වි-තැපෑලක් එකතු කරන්න", "scenes.app.workspaces.welcome_page.welcome_header": "ට්වේක් වෙත සාදරයෙන් පිළිගනිමු!", "scenes.apps.account.account.password.description": "ඔබගේ මුරපදය වෙනස් කරන්න.", "scenes.app.channelsbar.channelsworkspace.channel_title": "නාලිකා", - "scenes.login.forgot_password.password_dont_match": "ඔබගේ මුරපද නොගැලපේ හෝ ඒවා ඉතා කෙටි ය. අවම වශයෙන් අකුරු 8 ක් සහිත මුරපදයක් යොදන්න." + "scenes.login.forgot_password.password_dont_match": "ඔබගේ මුරපද නොගැලපේ හෝ ඒවා ඉතා කෙටි ය. අවම වශයෙන් අකුරු 8 ක් සහිත මුරපදයක් යොදන්න.", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "නව සබැඳියක් ජනනය කෙරිණි", + "scenes.app.popup.adduser.magiclinks.action_generate": "ජනනය කරන්න", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "සාර්ථකව පසුරුපුවරුවට පිටපත් කෙරිණි", + "scenes.app.popup.adduser.magiclinks.action_copy": "පිටපත්", + "scenes.app.popup.adduser.magiclinks.genrator_info": "වැඩබිටම ආරාධනා සබැඳිය", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "ඔබගේ වින්‍යාසය JSON ආකෘතියෙන් ජනනය කිරීමට ප්‍රලේඛනය වෙත යන්න.", + "scenes.app.popup.appsparameters.pages.publication_label": "ප්‍රකාශනය", + "scenes.app.popup.appsparameters.pages.publish_app_label": "යෙදුම ප්‍රසිද්ධ කරන්න", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "සමස්ථ සමාගමෙන්ම ඉවත් කරන්න", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "වැඩබිමෙන් ඉවත් කරන්න", + "scenes.app.popup.createworkspacepage.placeholder_name": "වැඩබිමේ නම", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "ජංගම දැනුම්දීම් වාරගණන සකසන්න.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "දැනුම්දීම් වාර ගණන", + "scenes.app.popup.appsparameters.pages.title_tester": "ට්වෙක්කේත අත්", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "වි-තැපැල් දැනුම්දීම් වාර ගණන සකසන්න.", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "පහත මූලපද ඉස්මතු කරන්න:", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "මෙම වැඩබිම හැරයන්න", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "වැඩබිම", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "මෙම වැඩබිමෙහි ඔබ සතුව කිසිම යෙදුමක් නැත", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "ඔබ වැඩබිමෙහි පරිපාලකයි.", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "එය ඉවත් කිරීමට ඔබ වැඩබිමේ තනිව සිටිය යුතුය. සහකාරකයින් ඉවත් කර යළි උත්සාහ කරන්න.", + "scenes.app.mainview.quick_search_placeholder": "ඉක්මන් සෙවුම", + "scenes.app.popup.userparameter.personnal_workspaces_title": "ඔබගේ වැඩබිම්", + "scenes.apps.drive.go_out_trash_menu": "කුණුකූඩය හැරයන්න", + "scenes.apps.drive.go_trash_menu": "කුණුකූඩයට යන්න", + "scenes.apps.messages.message.show_button": "දර්ශනය", + "scenes.apps.messages.message.show_responses_button": "සියළු උත්තර දකින්න", + "components.workspace.list_manager.current_space": "වත්මන් වැඩබිම", + "components.upload.drop_files": "සියළු ගොනු මෙහි දමන්න", + "components.tagpicker.tag_name": "අනන්‍යනයේ නම", + "components.reminder.hours_bef": "පැය කිහිපයකට පෙර", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "වියමන අඩවිය", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "අනුවාදය", + "scenes.app.integrations_parameters.company_applications_table.name": "නම", + "scenes.app.integrations_parameters.company_applications_table.title": "ඔබගේ සමාගම තුළ ස්ථාපිතයි", + "components.locked_features.locked_workspace_popup.subtitle": "නොමිලේ අනුවාදයෙහි, ඔබගේ සමාගම තුළ එක් වැඩබිමක් පමණක් ලද හැකිය.", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "වැණුම", + "components.locked_features.locked_drive_popup.title": "ඔබ ධාවකයේ සීමාවම ලඟා වී ඇත", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "සෑදූ දිනය", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "පෙන්වන්න", + "scenes.join.join_the_team_button": "කණ්ඩායමට එක්වන්න", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "සමාගමෙන් ඉවත් කරන්න", + "scenes.join.wrong_link_description": "ඔබට මෙම සමාගමට එක්වීමට ආරාධනා කළ පුද්ගලයාගෙන් නව සබැඳියක් විමසන්න හෝ ඔබගේම සමාගමක් සාදන්න", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "ඔබගේ සමාගමට {{$1}} සාර්ථකව එක් කෙරිණි", + "scenes.join.twake_description": "ට්වේක් යනු ඔබගේ කණ්ඩායම් ඵලදායිතාව වැඩිදියුණු කිරීම සඳහා ගොඩනගා ඇති විවෘත මූලාශ්‍ර සංඛ්‍යාංක වැඩබිමකි", + "scenes.apps.messages.input.replied_to": "වෙත පිළිතුරු දුණි ", + "components.searchpopup.tasks": "කාර්යයන්", + "scenes.join.loading": "පූරණය වෙමින්…", + "scenes.join.wrong_link_title": "මෙම සබැඳිය තවදුරටත් නැත", + "scenes.join.create_the_company_button": "සමාගම සාදන්න", + "scenes.join.login_first_button": "පුරන්න හෝ පළමුව ගිණුමක් සාදන්න", + "scenes.join.join_workspace_from_company": "{{$2}} වෙතින් {{$1}} හා එක්වන්න!", + "scenes.app.integrations_parameters.applications_table.name": "නම", + "scenes.app.integrations_parameters.title": "අනුකලන", + "scenes.app.integrations_parameters.applications_table.title": "වෙනත් අනුකලන", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "යෙදුම සොයන්න", + "scenes.app.integrations_parameters.company_application_popup.tag": "ස්ථාපිතයි", + "scenes.app.integrations_parameters.company_application_popup.btn": "ස්ථාපනය", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "තොරතුරු", + "scenes.app.workspaces.create_company.group_data.group_main_activity.printing_paper": "මුද්‍රණය / කඩදාසිය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.construction_building": "ඉදිකිරීම් / ගොඩනැගිලි ද්‍රව්ය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.materials": "ද්‍රව්ය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.chemistry": "රසායනය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.trade_commerce_distribution": "වෙළඳ / වාණිජ / බෙදා හැරීම", + "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "ප්‍රකාශනය / සන්නිවේදනය / බහුමාධ්‍ය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.studies_and_advice": "අධ්‍යයන සහ උපදෙස්", + "scenes.app.workspaces.create_company.group_data.group_main_activity.pharmaceutical_industry": "ඖෂධ කර්මාන්තය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.it_telecom": "තො.තා. / විදුලි සංදේශ", + "scenes.app.workspaces.create_company.group_data.group_type.company": "සමාගම හෝ සමාගමේ ක්‍රියාංශය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.entertainment": "විනෝදාස්වාදය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.textile_clothing_shoes": "රෙදි / ඇඳුම් / පාවහන්", + "scenes.app.workspaces.create_company.group_data.group_main_activity.research": "පර්යේෂණ", + "scenes.app.workspaces.create_company.group_data.group_main_activity.education": "අධ්යාපන", + "components.users_picker.add_me": "මාව එක්කරන්න", + "scenes.app.workspaces.create_company.invitations.title": "ඔබගේ වැඩබිම වින්‍යාසගත කරන්න.", + "scenes.apps.drive.right_preview.operations_delete": "කුණුකූඩයට ගෙනයන්න", + "scenes.apps.account.notifications.disturb_option_c": " (ස්ථානීය වේලාකලාපය)", + "scenes.apps.parameters.workspace_sections.workspace": "වැඩබිම", + "scenes.apps.parameters.group_sections.workspaces": "වැඩබිම්", + "scenes.apps.tasks.boards": "පුවරු", + "scenes.apps.tasks.task": "කාර්යය", + "scenes.apps.tasks.no_tasks": "කාර්යය නැත", + "scenes.apps.tasks.list_modal.archive_all_tasks": "සියළුම කාර්යය සංරක්‍ෂණය", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "({{$1}}) සංරක්‍ෂිත කාර්යය ඉවත්කරන්න", + "scenes.apps.tasks.new_board.title": "නව පුවරුව", + "scenes.apps.tasks.new_board.edit_title": "පුවරුව සංස්කරණය", + "scenes.apps.tasks.task.description": "සවිස්තරය", + "scenes.apps.tasks.task.assignees": "පැවරුම්ලාභීන්", + "scenes.app.workspaces.welcome_page.lets_go": "අපි යමු!", + "scenes.apps.account.account.emails.description": "ඔබගේ විවිධ වි-තැපැල් ලිපින කළමනාකරණය කරන්න.", + "scenes.login.create_account.step_2_subtitle_b": "ඔබගේ දු.ක. අංකය පෞද්ගලිකව තිබෙනු ඇත.", + "scenes.app.workspaces.create_company.company_name.title_2": "ඔබගේ සමාගමේ නම දක්වන්න.", + "scenes.app.workspaces.create_company.importations.title_1": "දැනටමත් සංඛ්‍යාංක මෙවලම් සමඟ වැඩ කරනවාද? දැන් ඔබගේ මෙවලම් ආයාත හෝ අනුකලනය කරන්න!", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "තවම කිසිවෙක් ඔබට වැඩබිමකට ආරාධනා කර නැති බව පෙනේ.", + "scenes.app.workspaces.welcome_page.see_you_soon": "ඉක්මණින් මුණගැසෙමු!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "ඔබගේ ගිණුමට වි-තැපැල් කිහිපයක් යෙදිය හැකිය; දැනුම්දීම් එවීමට එක් ලිපිනයක් පමණක් භාවිතා කෙරේ.", + "scenes.app.workspaces.welcome_page.done": "මම අහවරයි", + "scenes.apps.account.account.description_main": "ට්වේක් දැනුම්දීම් යවන්නේ ඔබගේ ප්‍රධාන ලිපිනයටය. භාවිතා කරන වැඩබිම් වෙත ස්වයංක්‍රීයව ආරාධනා ලැබීමට ද්විතීයික ලිපින ඉඩ සලසයි.", + "scenes.app.channelsbar.currentuser.logout": "වරන්න", + "app.name.twake_tasks": "කාර්යය", + "components.calendar.repetition.never": "කවදාවත්", + "components.calendar.repetition.years": "අවුරුදු", + "components.calendar.repetition.days": "දවස්", + "scenes.app.channelsbar.currentuser.create_workspace_page": "වැඩබිමක් සාදන්න", + "scenes.app.channelsbar.currentuser.workspace_parameters": "වැඩබිමේ සැකසුම්", + "scenes.app.channelsbar.currentuser.workspace_info": "ඔබ {{$2}} සමූහයෙන් {{$1}} වැඩබිමෙහි සිටී", + "components.calendar.repetition.after": "පසු", + "scenes.apps.account.identity.description": "අනෙකුත් ට්වේක් පරිශීලකයින්ට පෙනෙන ඔබගේ පළමු නම, අග නම සහ පැතිකඩ රූපය වෙනස් කරන්න.", + "scenes.apps.account.account.make_main": "ප්‍රධාන සකසන්න", + "components.locked_features.locked_workspace_popup.title": "ඔබට තවත් වැඩබිම් සෑදිය නොහැකිය", + "scenes.app.workspaces.create_company.group_data.title": "අපි ඉක්මන් කරන්නෙමු — ඇවැසි වන්නේ සංඛ්‍යාන තොරතුරු කිහිපයක් පමණි.", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "භූමිකාව", + "scenes.app.mainview.channel_description": "නාලිකාව විස්තර කරන්න", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "වැඩබිමේ සියළුම පරිශීලකයින්ට මෙම නාලිකාවට ස්වයංක්‍රීයව ආරාධනා කරන්න", + "scenes.client.channelbar.channelmemberslist.title": "{{$1}} හි පරිශීලකයින්", + "scenes.apps.parameters.workspace_sections.members.invite_all": "සියල්ලන්ට ආරාධනා කරන්න", + "scenes.apps.calendar.modals.reminder_add": "සිහිකැඳවුමක් එක්කරන්න", + "scenes.app.mainview.create_account": "ඔබගේ වැඩබිම නොමිලේ සාදන්න ", + "components.drive.right_preview.suppress_link": "සබැඳිය යටපත් කරන්න", + "components.workspace.list_manager.no_workspace": "වැඩබිම් නැත", + "components.workspace.list_manager.add": "වැඩබිම් එක්කරන්න", + "components.searchpopup.enter_text": "ට්වේක් හි සෙවුමට පාඨ කිහිපයක් යොදන්න.", + "components.searchpopup.filter_ws": "වැඩබිම් පෙරන්න", + "components.searchpopup.tags": "අනන්‍යයන", + "components.searchpopup.creation": "සෑදීම", + "components.searchpopup.update_search": "සෙවුම යාවත්කාල", + "scenes.apps.board.archived_tasks": "({{$1}}) සංරක්‍ෂිත කාර්යයන්", + "scenes.apps.board.active_tasks": "ක්‍රියාත්මක කාර්යයන්", + "scenes.apps.board.display_as": "ලෙස දර්ශනය", + "scenes.apps.board.new_task": "+ නව කාර්යය", + "scenes.apps.board.all_boards": "සියළු පුවරු", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "ට්වේක් නොමිලේ අනුවාදයේදී, ඔබට මෑත පණිවිඩ {{$1}} කට වඩා ප්‍රවේශ විය නොහැකිය.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "තව සැලසුම් පෙන්වන්න", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "වැඩබිමට පරිශීලකයින් හට ආරාධනා කරන්න.", + "scenes.app.channelsbar.company_invitation_alert_title": "ඔබට සමාගමට ආරාධනා කර ඇත ", + "scenes.app.popup.appsparameters.pages.alert_published_app": "ඔබගේ යෙදුම ප්‍රකාශනය කෙරිණි, එය සංස්කරණය කළ නොහැකිය.", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "ඔබ 'ස්වයංක්‍රීය' ක්‍රියාත්මක කළහොත්, මෙම සමාගමේ ඊළඟ වැඩබිම් වලට ද ස්වයංක්‍රීයව මෙම යෙදුම එකතු වේ.", + "components.reminder.minutes_bef": "විනාඩි කිහිපයකට පෙර", + "scenes.app.popup.appsparameters.pages.app_update": "{{$1}} යෙදුම යාවත්කාල කරන්න (වාර {{$2}} ක් භාවිතා කර ඇත.)", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "දර්ශන සැකසුම්", + "scenes.app.popup.appsparameters.pages.event_subtitle": "සිදුවීම්", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "ඔබ තවමත් යෙදුමක් සාදා නැත. යෙදුමක් හෝ සම්බන්ධකයක් සෑදීමට පෙර එය දැනටමත් යෙදුම් වෙළඳපොළෙහි නැති බව සහතික කරගන්න.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "ඔබගේ පණිවිඩය JSON ආකෘතියෙන් ලිවීමට අරඹන්න.", + "scenes.app.popup.appsparameters.pages.description_label": "වැණුම", + "scenes.app.popup.createworkspacepage.create_new_workspace": "නව වැඩබිමක් සාදන්න", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "යෙදුම යාවත්කාල වීමේදී දෝෂයක් සිදුවිණි.", + "scenes.app.popup.createworkspacepage.add_subtitle": "තව ඉඩ ඇවැසිද?", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "ඔබගේ යෙදුමෙහි සරළ කළ නම දැනටමත් වෙනත් යෙදුමක් භාවිතා කරයි. වෙනස් කරන්න.", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "රැඳෙමින්...", + "components.reminder.days_bef": "දවස් කිහිපයකට පෙර", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "මෙම වැඩබිමෙහි රූපය වෙනස් කරන්න", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "වි-තැපෑල හෝ පරිශීලක නාමය වලංගු දැයි පරීක්‍ෂා කරන්න.", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "යෙදුම මෙම වැඩබිමේ ස්ථාපනය කරන්න.", + "scenes.app.popup.workspaceparameter.pages.description": "වැණුම", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "පරිශීලකයින්ට ආරාධනය", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "සෙවුමට ආපසු", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "මෙම වැඩබිමෙහි යෙදුම්", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "පහත පරිශීලකයින්ට ආරාධනා කිරීමේදී දෝෂයක් සිදුවිණි: ", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "සමාගමේ අනෙකුත් පැතිවල ස්ථාපනය කර ඇති යෙදුම් {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "මෙම {{$1}} වැඩබිමේ ස්ථාපිත යෙදුම්", + "scenes.app.popup.workspaceparameter.pages.name_label": "වැඩබිමෙහි නම", + "scenes.app.popup.workspaceparameter.pages.name_description": "වැඩබිමෙහි නම වෙනස් කරන්න", + "components.reminder.weeks_bef": "සති කිහිපයකට පෙර", + "scenes.app.popup.workspaceparameter.pages.show_button": "දර්ශනය", + "scenes.app.popup.workspaceparameter.pages.title": "වැඩබිමේ සැකසුම්", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "මෙම වැඩබිමෙන් ඉවත් කරන්න", + "scenes.apps.calendar.modals.reminders": "සිහිකැඳවුම්", + "scenes.apps.calendar.modals.modify_event_button": "සිදුවීම සංස්කරණය", + "scenes.apps.calendar.modals.event_description_placeholder": "වැණුම", + "scenes.apps.calendar.modals.description_placeholder": "වැණුම", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} ගොනුවක් යවා ඇත.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} ගොනු කිහිපයක් යවා ඇත.", + "scenes.apps.calendar.workspace_menu": "වැඩබිම", + "scenes.apps.calendar.workspace_label": "මෙම වැඩබිම", + "scenes.apps.calendar.workspace": "වැඩබිම", + "scenes.apps.calendar.no_connectors_menu_text": "දින දසුනකට සම්බන්ධ කළ හැකි සම්බන්ධක කිසිවක් ඔබ සතුව නැත.", + "scenes.apps.calendar.no_calendar_text": "ඔබ මෙම වැඩබිමට කිසිම දින දසුනක් සකසා නැත.", + "scenes.apps.drive.throw_menu": "කුණුකූඩයට යවන්න", + "scenes.apps.messages.input.edited": "සංස්කරණය කළා", + "scenes.apps.drive.trash_empty_menu": "කුණුකූඩය හිස් කරන්න", + "scenes.apps.drive.viewer.no_preview_message": "මෙවැනි ගොනුවක් දැකීමට නොහැකිය.", + "scenes.apps.messages.just_you": "ඔබට පමණක් පෙනෙයි", + "scenes.apps.calendar.reminders": "සිහිකැඳවුම්", + "scenes.help_us": "කෙසේ වෙතත්, දෝෂය නිවැරදි කිරීමට අපට උදවු වීමට කැමති නම්, පහතින් පණිවිඩයක් එවන්න: ", + "components.tagpicker.notag": "අනන්‍යයන නැත", + "scenes.login.verifymail.error_message": "දෝෂයක් සිදුවුණි", + "scenes.no_panic": "කලබල නොවන්න! ට්වේක් නිවැරදි කිරීමට පිටුව යළි පූරණය කරන්න.", + "services.apps.calendar.event_icon": "සිදුවීම", + "services.apps.calendar.reminder_icon": "සිහිකැඳවීම", + "services.user.notification_parameters_update_alert": "දැනුම්දීමේ සැකසුම් යාවත්කාල කර ඇත.", + "services.user.update_password_alert": "ඔබගේ මුරපදය යාවත්කාල කර ඇත.", + "scenes.apps.drive.trash": "කුණුකූඩය", + "scenes.apps.messages.input.emoji": "ඉමෝජි", + "scenes.apps.messages.input.hide_formatting": "ආකෘතිකරනය සඟවන්න", + "scenes.apps.messages.input.show_formatting": "ආකෘතිකරනය පෙන්වන්න", + "scenes.apps.tasks.my_tasks": "මාගේ කාර්යය", + "scenes.apps.tasks.board.tasks.subtask": "අනු-කාර්යය", + "scenes.apps.tasks.board.place_holder": "පුවරුවේ නම", + "scenes.apps.tasks.board.tasks.add_subtask": "අනු-කාර්යක් එක්කරන්න", + "components.drive.elements.see": "දකින්න", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "ඇරයුම අවලංගු කරන්න", + "scenes.apps.tasks.active_tasks": "ක්‍රියාත්මක කාර්යය", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "යෙදුම් කළමනාකරණයට අදාළ තොරතුරු", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "වත්මන් වැඩබිමේ හැඳු.", + "scenes.client.channelbar.channelmemberslist.no_members": "නාලිකාවෙහි පරිශීලකයින් නැත, පරිශීලකයින් එක්කරන්න එබීමෙන් ආරාධනා කළ හැකිය.", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} සවිස්තරය වෙනස් කළා", + "components.alert.leave_private_channel.description": "ඇරයුමකින් තොරව ඔබට නැවත මෙම පෞද්ගලික නාලිකාවට එක්වීමට නොහැකි වනු ඇත.", + "components.add_mails_workspace.title_1": "කිහිප දෙනෙක් එක්කරන්න", + "components.add_mails_workspace.title_2": "ට්වේට් යනු කණ්ඩායම් සහයෝගීතා මෙවලමකි, එබැවින් අපි ඔබ වෙනුවෙන් සෑදූ වැඩබිම පරීක්‍ෂා කිරීමට පරිශීලකයින් කිහිප දෙනෙකුට ආරාධනා කරන්න.", + "components.add_mails_workspace.text_area_placeholder": "පරිශීලකයින්ගේ වි-තැපැල් ඇතුල් කරන්න*", + "components.verify_mail.title_1": "සුභ පැතුම්", + "components.verify_mail.title_2": "ඔබ දැන් නිල ට්වේට් පරිශීලකයෙකි!", + "components.verify_mail.button": "පරිශීලක එක්කරන්න", + "scenes.client.channels_bar.modals.guest_management.tips": "ඉහත ආදානය භාවිතයෙන් වි-තැපැල් එක්කිරීම හෝ සෙවීම අරඹන්න", + "scenes.app.popup.workspaceparameter.edit_from_console": "හසුරුවමෙහි බලන්න", + "services.console_services.toaster.add_emails_error": "වි-තැපැල් ලිපින(ය) එක්කිරීමේදී දෝෂයකි", + "components.locked_features.locked_history_banner.button": "තව දැනගන්න", + "components.locked_features.locked_guests_popup.title": "අමුත්තන්ගේ විශේෂාංගය අගුළු ලා ඇත", + "components.locked_features.locked_guests_popup.subtitle": "මෙම විශේෂාංගය ට්වේට් නොමිලේ අනුවාදයට නැත", + "components.locked_features.locked_guests_popup.learn_more_button": "තව දැනගන්න", + "components.on_boarding.popups.blocked_company.title": "ගෙවීමේ ගැටළුවක් නිසා ඔබගේ සමාගමට අගුළු ලා ඇත", + "scenes.apps.tasks.select_user_button": "වෙනත් පරිශීලකයෙකු සඳහා කාර්යයන් දකින්න", + "components.emoji_picker.categories.smileys_and_people": "මදහස හා මිනිසුන්", + "scenes.apps.account.notifications.devices_option_inactive": "මම ඩෙස්ක්ටොප් එකේ අක්‍රියව සිටින විට මට තල්ලු දැනුම්දීම් එවන්න", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Extension", + "scenes.apps.parameters.workspace_sections.members.pending": "පොරොත්තු ඊමේල්", + "scenes.login.home.unable_to_connect": "වලංගු නොවන අක්තපත්‍ර", + "scenes.login.create_account.step_1_subtitle": "එය සරල විය නොහැකිය — අපට ඇවැසි වන්නේ තොරතුරු ටිකක් පමණි.", + "scenes.login.create_account.step_3_mail_sent": "අපි ඔබට විද්‍යුත් තැපෑලෙන් සක්‍රිය කිරීමේ සබැඳියක් එවා ඇත.", + "scenes.login.create_account.step_3_subtitle": "අවසාන පියවර — ඔබ රොබෝ කෙනෙක් නොවන බව අපට තහවුරු කිරීමට අවශ්‍යයි!", + "scenes.app.workspaces.create_company.company_name.title_1": "පටන් ගැනීමට,", + "scenes.app.workspaces.welcome_page.added_to_company": "ඔබට ආරාධනා කර ඇත ", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "වෙනත් විද්‍යුත් තැපැල් ලිපිනයක් භාවිතා කරමින් ඔබට ආරාධනා කළේද?", + "scenes.app.workspaces.welcome_page.code_verification": "සත්යාපන කේතය", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "අපි ඔබට {{$1}} හරහා සත්‍යාපන කේතයක් එවා ඇත", + "scenes.apps.account.preference": "මනාප", + "components.calendar.repetition.monthly_on": "මාසිකව {{$1}} {{$2}}", + "scenes.apps.account.account.email_add_modal.confirm": "මෙම විද්‍යුත් තැපෑල තහවුරු කරන්න", + "components.calendar.repetition.does_not_repeat": "නැවත සිදු නොවේ", + "components.calendar.repetition.monthly_on_day": "මාසිකව දින {{$1}}", + "components.calendar.repetition.annually_on": "වාර්ෂිකව {{$1}}", + "components.calendar.repetition.repeat": "සෑම එකක්ම නැවත නැවත කරන්න", + "components.calendar.repetition.ends": "අවසන් වේ", + "components.calendar.repetition.custom_recurrence": "අභිරුචි පුනරාවර්තනය", + "components.calendar.repetition.occurrence": "සිදුවීම(ය)", + "components.calendar.repetition.repeat_on": "නැවත නැවත කරන්න", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "නැවත ක්‍රියාත්මක", + "components.searchpopup.only_pinned": "ඇමුණුම් කළ පණිවිඩ පමණි", + "components.blocked_account.trial_period_over": "ඔබේ අත්හදා බැලීමේ කාලය අවසන්. ඔබගේ ගිණුම අගුළු ඇරීමට සහ සියලු ක්‍රියාකාරීත්වයන් වෙත ප්‍රවේශය ලබා ගැනීමට, කරුණාකර ඔබගේ ගිණුම විද්‍යුත් තැපෑලෙන් තහවුරු කරන්න", + "components.verify_mail.text": "පළමුවෙන්ම, ඔබ ඔබගේ විද්‍යුත් තැපැල් ලිපිනය සත්‍යාපනය කළ යුතුය. අපි සත්‍යාපන සබැඳියක් යවා ඇත", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "ඊළඟ සිදුවීමේදී යවනු ලබන නිෂ්ක්‍රීය දත්ත", + "scenes.app.popup.appsparameters.pages.publication_description": "ඔබගේ යෙදුම පෙන්වීම නිශ්චය කරන්න.", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "කියවීමේ වරප්‍රසාදය", + "scenes.app.popup.appsparameters.pages.remove_app": "යෙදුම {{$1}} ස්ථිරවම මකන්න.", + "scenes.app.popup.appsparameters.pages.status_tilte": "තත්වය", + "scenes.app.popup.appsparameters.pages.string_information": "මෙම තන්තුව ඔබගේ යෙදුම හඳුනා ගන්නා අතර පණිවිඩ විධානවල භාවිතා කරනු ඇත.", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "සිදුවීම් පිළිගැනීමේ Url", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "ඔබට දැනුම්දීම් නොලැබෙන කාල සීමාවක් තෝරන්න.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "කාර්ය ඉඩ මකන්න", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "ඔබට මෙම කාර්ය ඉඩ මැකීමට අවශ්‍ය බව තහවුරු කිරීමට, කරුණාකර පහත නම ටයිප් කර මකන්න ඔබන්න.", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "වැඩබිමේ මැදිහත්කරු", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "ඔබ අවසන් පරිපාලකයා වන නිසා ඔබට වැඩබිම හැර යා නොහැක. ඔබට නව පරිපාලකයෙකු නිර්වචනය කිරීමට හෝ මෙම කාර්ය ඉඩ මකා දැමීමට/සංරක්ෂිත කිරීමට හැකිය.", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "ගෙවීම් සහ දායකත්වයන්", + "scenes.apps.drive.choose_folder_button": "නාමාවලියක් තෝරන්න", + "scenes.apps.drive.choose_file_button": "ගොනුවක් තෝරන්න", + "components.alert.confirm_click": "OK ක්ලික් කිරීමෙන් ඔබගේ ක්‍රියාව තහවුරු කරන්න.", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "ඔබේ සමාගමෙන් {{$1}} සාර්ථකව මකා ඇත", + "general.delete": "මකන්න", + "general.unarchive": "අසංරක්ෂණය", + "general.confirm": "තහවුරු කරන්න", + "general.connexion_status.disconnected": "ඔබ නොබැඳිය", + "general.connexion_status.connected": "ඔබ මාර්ගගත යි", + "scenes.app.side_app.messages_thread_title": "{{$1}} • Messages thread", + "scenes.app.workspaces.create_company.group_data.group_main_activity.bank": "බැංකුව / රක්ෂණය", + "scenes.app.workspaces.create_company.group_data.group_main_activity.real_estate": "දේපළ වෙළදාම්", + "scenes.app.workspaces.create_company.group_data.group_main_activity.electronics_electricity_energy": "ඉලෙක්ට්රොනික / විදුලි / බලශක්ති", + "scenes.app.workspaces.create_company.group_data.group_main_activity.machinery_automotive": "යන්ත්‍රෝපකරණ / වාහන", + "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "ප්රවාහන / සැපයුම්", + "components.user_picker.modal_no_result": "ප්‍රතිඵල හමු නොවිණි", + "scenes.apps.calendar.calendar.list_btn": "ලැයිස්තුව", + "scenes.apps.drive.navigators.navigator_labels.title": "ලේබල්", + "scenes.apps.drive.preview_bloc.error_file": "ගොනුව හමු නොවිණි", + "scenes.apps.messages.chatbox.chat.delete_message": "මෙම පණිවිඩය මකන්න", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "පණිවිඩය මකන්න", + "scenes.apps.messages.left_bar.stream.notifications.never": "කිසිවක් නැත", + "scenes.apps.account.title": "Account parameters", + "scenes.apps.account.notifications.keywords_placeholder": "සංවර්., වයිෆයි, කේතය, ...", + "scenes.apps.account.notifications.disturb_option_a": "අතර මට තල්ලු දැනුම්දීම් එවන්න එපා ", + "scenes.apps.account.notifications.devices_option_ever": "සෑම විටම මට තල්ලු දැනුම්දීම් එවන්න", + "scenes.apps.account.notifications.devices_option_never": "මට කිසිවිටක තල්ලු දැනුම්දීම් එවන්න එපා", + "scenes.apps.tasks.unconfigured_tab": "මෙම ටැබය තවම වින්‍යාස කර නොමැත.", + "scenes.apps.tasks.choose_board_button": "පුවරුවක් තෝරන්න", + "scenes.apps.tasks.task_status.todo": "කිරීමට", + "scenes.apps.tasks.task_status.done": "අහවර", + "scenes.apps.tasks.list_modal.modify_list": "ලැයිස්තුව වෙනස් කරන්න", + "scenes.apps.tasks.list_modal.new_list": "නව ලැයිස්තුව", + "scenes.apps.tasks.list_modal.remove": "ලැයිස්තුව සහ කාර්යයන් ඉවත් කරන්න", + "scenes.apps.tasks.list_modal.predefined_participants": "පූර්ව නිශ්චිත සහභාගිවන්නන්", + "scenes.login.forgot_password.text": "ඔබගේ අනන්‍යතාවය තහවුරු කිරීම සඳහා ඔබට විද්‍යුත් තැපෑලෙන් ඉලක්කම් 9ක කේතයක් ලැබෙනු ඇත.", + "scenes.login.forgot_password.password2": "මුරපදය තහවුරු කරන්න", + "components.emoji_picker.categories.not_found": "ඉමොජි හමු නොවිණි", + "scenes.app.taskpicker.select": "තෝරන්න", + "components.drive.navigators.directory_not_found": "නාමාවලිය හමු නොවිණි.", + "components.drive.modify_uslist": "පරිශීලක ලැයිස්තුව වෙනස් කරන්න", + "components.searchpopup.last_modif": "අවසාන වෙනස් කිරීම", + "components.alert.confirm": "ඔබේ ක්‍රියාව තහවුරු කරන්න", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "පණිවිඩ අංකය", + "scenes.app.channelsbar.channel_removing": "නාලිකාව මකන්න", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "සංවිධානාත්මකව සිටීමට රාමුව මත එබීමෙන් මෙම නාලිකා ඔබගේ ව්‍යාපාරයට ආයාත කළ හැකිය.", + "scenes.app.channelsbar.initial_instructions_tutorial": "මුල් නමක්, නමක් සහ පැතිකඩ පින්තූරයක් තෝරන්න.", + "scenes.app.channelsbar.installation_desktop_tutorial": "ඩෙස්ක්ටොප් යෙදුම ස්ථාපනය කරන්න", + "scenes.app.channelsbar.tutorial_alert": "මෙම රාමුව යළි නොපෙන්වන්නද?", + "scenes.app.channelsbar.welcoming_message_subtitle": "ක්ලික් කිරීම් කිහිපයකින් Twake pro කෙනෙක් වන්න!", + "scenes.app.mainview.instruction_current_tab": "ඔබගේ වම් පස ඇති නාලිකාවක් තේරීමෙන් ආරම්භ කරන්න.", + "scenes.app.popup.adduser.adresses_message": "කරුණාකර ලිපින කොමාවකින් හෝ ඉඩකින් වෙන් කරන්න. Twake ඔබගේ දායකත්වය මත පදනම්ව ආරාධනා ගණන සීමා කළ හැකි බව මතක තබා ගන්න.", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "ඔබගේ Twacode පණිවිඩවල පෙනුම පරීක්ෂා කරන්න", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "යෙදුමට සංස්කරණය සහ කියවීමට හැකි දේ නියම කරන්න.", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "යෙදුමේ වරප්‍රසාද", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "ඔබගේ අයදුම්පත්‍රය ප්‍රකාශනය දැනට Twake කණ්ඩායම විසින් වලංගු කිරීමක් බලාපොරොත්තුවෙන් සිටී.", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "උදාසීන '{{$3}}' සහිත '{{$1}}' සහ id '{{$2}}' වර්ගයේ සිදුවීම", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "යෙදුම මකන්න", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "යෙදුම පෙන්වන්නේ කොතැනදැයි නියම කිරීමට ඔබට ඉඩ සලසයි.", + "scenes.app.popup.appsparameters.pages.error_message": "මෙම නම දැනටමත් වෙනත් යෙදුමක් විසින් භාවිතා කර ඇත; කරුණාකර වෙනත් එකක් තෝරන්න.", + "scenes.app.popup.appsparameters.pages.filter_information": "මෙම පෙරහන ඔබගේ API යතුර ඔබගේ සම්බන්ධකයේ ඇති සේවාදායකයන්ට පමණක් භාවිතා කිරීම සීමා කරයි.", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "මෙම නම දැනටමත් වෙනත් යෙදුමකින් භාවිතා වේ. කරුණාකර වෙනත් එකක් තෝරන්න.", + "scenes.app.popup.appsparameters.pages.installation": "ස්ථාපනය කරන්න.", + "scenes.app.popup.appsparameters.pages.optimal_format": "ප්රශස්ත ආකෘතිය: 48x48px.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "ප්‍රකාශනය නොකළ යෙදුම ඔබේ සමාගම තුළ පමණක් ක්‍රියා කරයි. ඔබට එය සියලුම Twake පරිශීලකයින්ට ලබා දීමට අවශ්‍ය නම්, මෙම විකල්පය සක්‍රිය කරන්න.", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "ලිවීමේ වරප්‍රසාද", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "You can not delete this app if it is published.", + "scenes.app.popup.appsparameters.pages.remove_app_button": "යෙදුම මකන්න", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "මනාප සංදර්ශන කරන්න", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "webhooks වෙත ප්‍රවේශය", + "scenes.apps.calendar.export_view_menu": "Export the view...", + "scenes.apps.calendar.ics_subscription_menu": "ICS දායකත්ව සබැඳියක් ලබා ගන්න", + "scenes.apps.calendar.modals.remove_button": "මකන්න", + "scenes.apps.calendar.modals.remove_event_button": "සිදුවීම මකන්න", + "scenes.apps.calendar.modals.remove_event_text": "සිදුවීම මකන්නද?", + "scenes.apps.calendar.remove_calendar_confirmation": "දින දර්ශනය සහ එහි සිදුවීම් ස්ථිරවම මකන්නද?", + "scenes.apps.drive.message_added_file": "{{$1}} {{$2}} යවන ලදී.", + "scenes.apps.drive.remove_definitely_menu": "ස්ථිරවම මකන්න", + "scenes.apps.drive.unconfigured_tab": "මෙම ටැබය තවම වින්‍යාස කර නොමැත.", + "scenes.apps.messages.message.pin_button": "Pin message", + "scenes.apps.messages.message.unpin_button": "පණිවිඩය ඇමුණුම ඉවත් කරන්න", + "scenes.apps.messages.message.pinned": "පින් කර ඇත", + "scenes.apps.messages.message.remove_button": "මකන්න", + "scenes.login.verifymail.success": "ඔබගේ විද්‍යුත් තැපෑල සාර්ථකව සත්‍යාපනය කරන ලදී!", + "scenes.login.verifymail.verification_waiting": "සත්‍යාපනය සඳහා රැඳී සිටිමින්...", + "services.apps.messages.no_command_possible": "'{{$2}}' නොපවතින නිසා හෝ විධාන සෑදීමට ඉඩ නොදෙන නිසා අපට '{{$1}}' විධානය ක්‍රියාත්මක කළ නොහැක.", + "scenes.apps.calendar.unconfigured_tab": "මෙම ටැබය තවම වින්‍යාස කර නොමැත.", + "scenes.apps.drive.top_menu_no_items": "{{$1}} items", + "scenes.apps.drive.viewer.download_desktop": "යෙදුමේ පෙරදසුන් කිරීමට Twake Desktop බාගන්න", + "scenes.apps.tasks.board.tasks.use_deadline": "නියමිත කාළය භාවිතය", + "scenes.apps.tasks.board.tasks.use_starttime": "ආරම්භක වේලාව භාවිතය", + "scenes.apps.tasks.board.tasks.in_list": "ලැයිස්තුවේ", + "scenes.apps.tasks.board.starts": "ආරම්භ කරයි", + "scenes.apps.tasks.board.ends": "සඳහා සිදු කළ යුතුය", + "scenes.apps.tasks.board.list_name": "ලැයිස්තුවේ නම", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "සමාගමේ අනුරුව සංස්කරණය ", + "scenes.apps.account.account.send_info": "මෙම අක්තපත්‍ර තොරතුරු ඔබේ පරිශීලකයාට යවන්න.", + "components.drive.elements.configurate_mod": "මැදිහත්කරු වින්‍යාසගත කරන්න...", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "නව ටැබ් එකක් සාදන්න", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} ඊමේල්(ය) එකතු වනු ඇත", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} නාලිකාවට {{$2}} එක් කළේය", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} {{$2}} නාලිකාවෙන් ඉවත් කරන ලදී", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} නව {{$2}} ටැබයක් {{$3}} එක් කරන ලදී", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} {{$2}} ටැබය {{$3}} ඉවත් කරන ලදී", + "general.verify": "තහවුරු කරන්න", + "components.unverified_account.typography_text_danger": "ඔබගේ අත්හදා බැලීමේ කාල සීමාව තුළ ඔබට {{$1}} දින(ය) ඉතිරිව ඇත. අත්හදා බැලීමේ ගිණුම දින 7කට පසු අවහිර කරනු ලබන අතර ලියාපදිංචි වී මාස 1කට පසු ස්ථිරවම මකා දමනු ලැබේ. අපි ඔබට එවූ සත්‍යාපන විද්‍යුත් තැපෑලෙහි \"මගේ ගිණුම සත්‍යාපනය කරන්න\" බොත්තම ක්ලික් කිරීමෙන් ඔබට ඔබගේ ගිණුම සත්‍යාපනය කළ හැක.", + "components.unverified_account.verification_details": "අපි සත්‍යාපන විස්තර යවා ඇත", + "components.account_verication_status_unverified": "තහවුරු නොකළ", + "components.verify_mail.paragraph": "ඔබට අවශ්‍ය නම් ඔබට එය පසුව කළ හැකි නමුත් සත්‍යාපනය නොකළ ගිණුම්වලට ප්‍රවේශය ඇත්තේ Twake හි සීමිත අනුවාදයකට පමණි", + "services.console_services.toaster.success_verify_email": "ඔබගේ විද්‍යුත් තැපැල් ගිණුමට සත්‍යාපන සබැඳියක් යවා ඇත", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "අමුත්තන් හෝ තිබෙන වි-තැපැල් සොයන්න", + "general.user.deleted": "මකා දැමූ ගිණුම", + "components.richtexteditor.toolbar.bold": "මහත", + "components.richtexteditor.toolbar.italic": "ඇල", + "components.richtexteditor.toolbar.strikethrough": "පහර හරහා", + "components.richtexteditor.toolbar.unordered-list": "බුලටිත ලැයිස්තුව", + "components.richtexteditor.toolbar.ordered-list": "ඇණවුම් කළ ලැයිස්තුව", + "components.richtexteditor.toolbar.blockquote": "වාරණ උපුටා දැක්වීම", + "components.richtexteditor.toolbar.code-block": "Code Block", + "components.locked_features.locked_history_banner.description": "ඔබේ සමාගමට පණිවිඩ ගොඩක් තිබේ! ඔබගේ සියලුම පණිවිඩ ඉතිහාසයට ප්‍රවේශ වීමට දැන් උත්ශ්‍රේණි කරන්න.", + "components.locked_features.locked_guests_popup.description": "අපොයි!! ඔබට ඔබේ වැඩබිමට බාහිර පරිශීලකයින්ට ආරාධනා කිරීමට අවශ්‍ය බව පෙනේ. ඔබට අමුත්තන් සහ බාහිර හවුල්කරුවන් සමඟ සහයෝගයෙන් කටයුතු කිරීමට අවශ්‍ය නම් ඔබේ සැලසුම උත්ශ්‍රේණි කිරීම සලකා බැලීමට ඔබට අවශ්‍ය විය හැකිය. අපගේ මිලකරණ විකල්ප ගවේෂණය කර ඔබේ කණ්ඩායම් සහයෝගීතා අවශ්‍යතා සඳහා හොඳම විකල්පය තෝරන්න.", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "ඔබේ සමාගම් දායකත්වයේ ගැටලුවක් තිබේ. කරුණාකර ඔබේ එක බලන්න", + "components.on_boarding.company_billing_banner.guest_or_member_text": "ඔබේ සමාගම් දායකත්වයේ ගැටලුවක් තිබේ. කරුණාකර සමාගමේ හිමිකරු හෝ පරිපාලක අමතන්න!", + "components.on_boarding.company_billing_banner.link": "සමාගම් දායක සැලැස්ම", + "components.on_boarding.popups.blocked_company.description": "Twake වෙත ඔබගේ දායකත්වය කල් ඉකුත් වී ඇත. කරුණාකර එය අලුත් කිරීමට සහ ඔබේ කණ්ඩායම සමඟ නැවත සන්නිවේදනය කිරීමට හැකි වීම සඳහා ඔබේ සමාගමේ හිමිකරු හෝ පරිපාලක අමතන්න!", + "components.on_boarding.popups.blocked_company.learn_more_text": "සමාගම් දායක සැලැස්ම ගැන තව දැන ගැනීමට අවශ්‍යද?", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "ඔබ මෙම පණිවිඩය මකා ඇත", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} ඔහුගේ පණිවිඩය මකා ඇත", + "components.locked_features.locked_workspace_popup.text": "අපොයි!! ඔබේ සමාගම තුළ නව වැඩ ඉඩක් නිර්මාණය කිරීමට ඔබට අවශ්‍යද? ඔබට ඔබේ සැලසුම උත්ශ්‍රේණි කිරීම සලකා බැලීමට අවශ්‍ය විය හැකිය. අපගේ මිලකරණ විකල්පයන් ගවේෂණය කර ඔබගේ කණ්ඩායම් සහයෝගීතා අවශ්‍යතා සඳහා හොඳම තේරීම තෝරන්න.", + "components.locked_features.locked_only_office_popup.text": "අපොයි!! ඔබට Twake වෙතින් ගොනුව සංස්කරණය කිරීමට අවශ්‍ය බව පෙනේ. ඔබට කාර්යාල ලිපිගොනු වටා සහයෝගයෙන් කටයුතු කිරීමට අවශ්‍ය නම් ඔබේ සැලසුම උත්ශ්‍රේණි කිරීම සලකා බැලීමට ඔබට අවශ්‍ය විය හැකිය. අපගේ මිලකරණ විකල්ප ගවේෂණය කර ඔබේ කණ්ඩායම් සහයෝගීතා අවශ්‍යතා සඳහා හොඳම විකල්පය තෝරන්න.", + "general.resume": "අරඹන්න", + "general.pause": "Pause", + "login.create_account": "ගිණුම තනන්න", + "'": "'", + "scenes.apps.messages.message.types.no_message_in_thread": "තවම කිසිවෙක් පිළිතුරු දුන්නේ නැත.", + "\"": "\"", + "scenes.app.channelsbar.currentuser.reset": "යළි පිහිටුවන්න", + "login.login_error": "පුරනය වීමේදී දෝෂයකි", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "තවම කිසිවෙකු ඔබට වැඩබිමකට ආරාධනා කර නැත.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "පෙරනිමි වැඩබිම", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "මෙම නාලිකාවට සියලුම වැඩ ඉඩ භාවිතා කරන්නන්ට ස්වයංක්‍රීයව ආරාධනා කරන්න", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "ඔබ {{$1}} මැකීමට ආසන්නයි", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "ඔබට තවමත් {{$2}} හි {{$1}} සාමාජිකයින් සිටී. මෙම කාර්ය ඉඩ මකා දැමීමට හැකි වන පරිදි ඔබ සියලුම සාමාජිකයින් ඉවත් කළ යුතුය.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "මගේ වැඩබිමේ සියලුම පණිවිඩ සහ ගොනු මකා දමන බව මට වැටහෙනවා.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "උපරිම ලාංඡන ප්‍රමාණය 5mb වේ", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "නරක ආකෘතිය, png gif සහ jpg පමණක් අවසර ඇත", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "නොදන්නා දෝෂයකි", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "දෝෂයකි", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "පරිශීලකයන් සංදර්ශන කිරීමට අවම වශයෙන් අකුරු තුනක් ලියන්න", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "පරිශීලකයෙකු හමු නොවීය", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "ඉමොජි හමු නොවීය", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "විධානයක් හමු නොවීය", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} ලියනවා...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} සහ {{$2}} ලියනවා...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} සහ {{$3}} තවත් පරිශීලකයින් ලියන්නේ...", + "components.locked_features_components.locked_invite_alert.message_part_1": "ඔබේ සමාගම එහි උපරිම සාමාජිකයින්ගේ {{$1}} සීමාවට ළඟා වී ඇත. කරුණාකර ", + "components.locked_features_components.locked_invite_alert.message_link": "ඔබේ සමාගම උසස් කරන්න", + "components.locked_features_components.locked_invite_alert.message_part_2": " තවත් සාමාජිකයින්ට ආරාධනා කිරීමට.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " ඔබේ සමාගමේ හිමිකරු හෝ පරිපාලක අමතන්න.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "කොන්සෝලය මත මගේ සියලුම සමාගම් සාමාජිකයින් බලන්න", + "scenes.app.popup.appsparameters.pages.application_creator.title": "නව ඒකාබද්ධ කිරීම", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "මෙම සමාගමේ හිමිකරුට සහ පරිපාලකයින්ට මෙම යෙදුම වෙනස් කිරීමට සහ ප්‍රකාශ කිරීමට හැකි වනු ඇති බව මට වැටහේ.", + "twake.application.access.title": "ඔබගේ යෙදුම සඳහා නිවැරදි විෂය පථයන් තෝරන්න.", + "twake.application.access.no_default_scopes_available'": "මෙම අනුකලනයට කිසිදු {{$1}} ප්‍රවේශයක් නොමැත", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake API ලේඛනගත කිරීම", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "ඔබ මේවා පුරවන්නේ කෙසේදැයි නොදන්නේ නම්, යන්න ", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "යෙදුම සාර්ථකව ඉවත් කරන ලදී {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "යෙදුම ඉවත් කිරීමේදී දෝෂයක් {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "{{$1}} යෙදුම සාර්ථකයි!", + "scenes.app.integrations_parameters.add_application": "නව ඒකාබද්ධ කිරීම", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "සංවර්ධක සැකසුම්", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "ඔබේ යෙදුම වචන කිහිපයකින් විස්තර කරන්න", + "scenes.app.popup.appsparameters.pages.app.private_key": "පුද්ගලික යතුර", + "components.rich_text_editor.plugins.suggestions.loading": "තව හොයනවා", + "components.open_desktop_popup.subtitle": "Twake යෙදුම තුළ විවෘත කරන ලදී", + "components.open_desktop_popup.open_here_link": "ඒ වෙනුවට මෙතන විවෘත කරන්න", + "molecules.download_banner.title": "Twake වලින් උපරිම ප්‍රයෝජන ලබා ගන්න, දැන් ඩෙස්ක්ටොප් යෙදුම බාගන්න", + "molecules.download_banner.download_button": "ඩෙස්ක්ටොප් යෙදුම බාගන්න", + "scenes.app.channelsbar.channel_copy_link": "නාලිකා සබැඳිය පිටපත් කරන්න", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "සාර්ථකව යාවත්කාලීන කරන ලදී", + "components.searchpopup.no_results_for": "සඳහා ප්‍රතිඵල තිබුණේ නැත", + "components.searchpopup.try_new_search": "නව සෙවීමක් උත්සාහ කරන්න", + "components.searchpopup.all": "සියලුම", + "components.searchpopup.chats": "කතාබස්", + "components.searchpopup.media": "මාධ්ය", + "components.searchpopup.files": "ගොනු", + "components.searchpopup.recent_chats": "මෑත කතාබස්", + "components.searchpopup.recent_media": "මෑත මාධ්ය", + "components.searchpopup.recent_files": "මෑත ගොනු", + "components.searchpopup.recent_channels_and_contacts": "මෑත නාලිකා සහ සම්බන්ධතා", + "components.searchpopup.header_title": "සොයන්න", + "components.searchpopup.scope.company": "සියලුම සමාගම තුළ", + "components.searchpopup.scope.channel": "මෙම නාලිකාවේ", + "components.searchpopup.channels": "නාලිකා", + "components.searchpopup.messages": "පණිවිඩ" } diff --git a/twake/frontend/public/locales/tr.json b/twake/frontend/public/locales/tr.json index 6c923a856b..635cdb11ad 100644 --- a/twake/frontend/public/locales/tr.json +++ b/twake/frontend/public/locales/tr.json @@ -63,5 +63,848 @@ "scenes.app.workspaces.create_company.group_data.group_main_activity.publishing_communication_multimedia": "Yayıncılık / İletişim / Multimedya", "scenes.app.workspaces.create_company.group_data.group_main_activity.transport_logistics": "Taşımacılık / Lojistik", "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "Yönetim", - "components.drive_dropzone.uploading": "Yüklüyor..." -} \ No newline at end of file + "components.drive_dropzone.uploading": "Yüklüyor...", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "Ödemeler ve abonelikler", + "scenes.app.workspacesbar.components.change_company_title": "Şirket değiştir", + "scenes.app.workspacesbar.components.create_company_menu": "Bir şirket oluşturun", + "scenes.apps.calendar.no_calendar_text": "Bu çalışma alanı için herhangi bir takvim ayarlamadınız.", + "scenes.apps.calendar.no_connectors_menu_text": "Bir takvime bağlanabilecek bağlayıcınız yok.", + "scenes.apps.calendar.remove_calendar_confirmation": "Takvim ve etkinlikleri kalıcı olarak silinsin mi?", + "scenes.apps.calendar.today_menu": "Bugün", + "scenes.apps.calendar.week_option": "Hafta", + "scenes.apps.calendar.workspace": "çalışma alanı", + "scenes.apps.calendar.workspace_label": "Bu çalışma alanı", + "scenes.apps.calendar.workspace_menu": "çalışma alanı", + "scenes.apps.drive.add_button": "Ekle", + "scenes.apps.drive.message_added_file": "{{$1}}, {{$2}} gönderdi.", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} birden fazla dosya gönderdi.", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} bir dosya gönderdi.", + "scenes.apps.messages.input.edited": "Düzenlendi", + "scenes.apps.messages.just_you": "Yalnızca size görünür", + "scenes.apps.messages.message.new_messages_bar": "Yeni mesajlar", + "scenes.apps.messages.message.cancel_button": "İptal", + "scenes.apps.messages.message.modify_button": "Düzenlemek", + "scenes.apps.messages.message.pin_button": "Pin mesajı", + "scenes.apps.messages.message.unpin_button": "Mesajın sabitlemesini kaldır", + "scenes.apps.messages.message.copy_link": "Bağlantıyı mesaja kopyala", + "scenes.apps.messages.message.pinned": "sabitlenmiş", + "scenes.apps.messages.message.remove_button": "Silmek", + "scenes.apps.messages.message.reply_button": "Cevap vermek", + "scenes.apps.messages.message.save_button": "Kaydetmek", + "scenes.apps.messages.message.show_button": "Görüntülemek", + "scenes.apps.messages.message.show_responses_button": "Tüm yanıtları görüntüle", + "scenes.apps.messages.message.types.first_channel_message_text": "Bu kanalın ilk mesajı", + "scenes.apps.messages.message.types.first_message_text": "Bu ilk mesaj", + "scenes.apps.messages.messageslist.get_writing_user": "yazıyor...", + "services.apps.messages.no_app": "Bu uygulama mevcut değil.", + "services.apps.messages.no_command_possible": "'{{$1}}' komutunu çalıştıramıyoruz çünkü '{{$2}}' mevcut değil veya komut oluşturmaya izin vermiyor.", + "services.user.notification_parameters_update_alert": "Bildirim ayarları güncellendi.", + "scenes.apps.drive.right_preview.public": "Kamu erişim", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Uygulamalarınızı ve bağlayıcılarınızı yönetin.", + "scenes.app.popup.appsparameters.pages.title_informations": "Temel bilgiler", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "Uygulama yönetimi ile ilgili bilgiler", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "Geçerli kullanıcı kimliği", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "Geçerli çalışma alanı kimliği", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Geçerli grup kimliği", + "scenes.app.mainview.channel_description": "Kanalı tanımlayın", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "Tüm çalışma alanı kullanıcılarını otomatik olarak bu kanala davet et", + "components.locked_features.locked_guests_popup.subtitle": "Bu özellik Twake'in ücretsiz sürümünde mevcut değildir.", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "Şirket aboneliğinizle ilgili bir sorun var. Lütfen, kendinize bir göz atın", + "components.on_boarding.company_billing_banner.guest_or_member_text": "Şirket aboneliğinizle ilgili bir sorun var. Lütfen şirket sahibi veya yöneticisi ile iletişime geçin!", + "components.on_boarding.company_billing_banner.link": "şirket abonelik planı", + "components.on_boarding.popups.blocked_company.title": "Bir ödeme sorunu nedeniyle şirketiniz kilitlendi", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "Buraya Tıkla", + "components.locked_features.locked_only_office_popup.subtitle": "Ücretsiz sürümde sadece ofis kullanamazsınız.", + "scenes.app.integrations_parameters.title": "Entegrasyonlar", + "scenes.app.integrations_parameters.applications_table.name": "İsim", + "scenes.app.integrations_parameters.applications_table.title": "Diğer entegrasyonlar", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Uygulama ara", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "İnternet sitesi", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Oluşturulma tarihi", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "sürüm", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "{{$1}} şirketinizden başarıyla silindi", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "{{$1}} şirketinize başarıyla eklendi", + "scenes.apps.messages.input.replied_to": "yanıtladı ", + "scenes.join.login_first_button": "Önce giriş yapın veya bir hesap oluşturun", + "scenes.join.join_the_team_button": "Takıma katıl", + "scenes.apps.account.title": "Hesap parametreleri", + "scenes.apps.account.account.menu_title": "Hesap", + "scenes.apps.account.languages.menu_title": "Dilim", + "scenes.apps.account.account.firstname": "İlk adı", + "scenes.apps.account.account.lastname": "Soyadı", + "scenes.apps.account.account.username": "Kullanıcı adı", + "scenes.apps.account.account.change_username": "Benzersiz kullanıcı adınızı değiştirin.", + "scenes.apps.account.account.emails": "e-postalar", + "scenes.apps.account.account.main_email": "ana e-posta", + "scenes.apps.account.account.email_add": "Yeni e-posta ekle", + "scenes.apps.account.account.email_add_modal.invalid_code": "Bu kod geçersiz", + "scenes.apps.account.account.password": "Parola", + "scenes.apps.account.account.password_modal.old_password": "Şimdiki Şifre", + "scenes.apps.account.account.password_modal.password": "Yeni Şifre", + "scenes.apps.account.account.password_modal.bad_old_password": "Eski şifre doğru değil.", + "scenes.apps.account.account.password_modal.bad_password": "Şifreleriniz uyuşmuyor veya çok kısa. Lütfen en az 8 karakterden oluşan bir şifre giriniz.", + "scenes.apps.account.account.logout": "Çıkış Yap", + "scenes.apps.account.notifications.title": "Bildirimler", + "scenes.apps.account.notifications.keywords_subtitle": "anahtar kelimeler", + "scenes.apps.account.notifications.keywords_placeholder": "dev, wifi, kod, ...", + "scenes.apps.account.notifications.disturb_option_a": "arasında bana push bildirimleri gönderme ", + "scenes.apps.account.notifications.disturb_option_b": " ve ", + "scenes.apps.account.notifications.disturb_option_c": " (yerel saat dilimi)", + "scenes.apps.account.notifications.devices_subtitle": "Cihaz bildirimleri", + "scenes.apps.account.notifications.devices_option_ever": "Bana her zaman push bildirimleri gönder", + "scenes.apps.account.notifications.devices_option_inactive": "Masaüstünde etkin olmadığımda bana anında iletme bildirimleri gönder", + "scenes.apps.account.notifications.devices_option_never": "Bana asla push bildirimleri gönderme", + "scenes.apps.account.notifications.privacy_subtitle": "Mahremiyet", + "scenes.apps.account.notifications.mail_subtitle": "E-posta Bildirimleri", + "scenes.apps.account.notifications.sound": "Sesli bildirim", + "scenes.apps.parameters.group_sections.apps.badge_extension": "Uzantı", + "scenes.apps.parameters.workspace_sections.members.members": "Kullanıcılar", + "scenes.apps.parameters.workspace_sections.members.pending": "bekleyen e-postalar", + "scenes.apps.parameters.workspace_sections.members.invite": "Yeni kullanıcı davet et", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "Kullanıcı Ekle", + "scenes.apps.tasks.new_board.title": "Yeni tahta", + "scenes.apps.tasks.new_board.edit_title": "Panoyu düzenle", + "scenes.apps.tasks.task": "Görev", + "scenes.apps.tasks.no_tasks": "Sorma", + "scenes.apps.tasks.task_status.todo": "Yapmak", + "scenes.apps.tasks.task_status.current": "Akım", + "scenes.apps.tasks.task_status.done": "Tamamlandı", + "scenes.apps.tasks.task.description": "Açıklama", + "scenes.apps.tasks.task.assignees": "atananlar", + "scenes.apps.tasks.task.edit.dates": "Tarih", + "scenes.apps.tasks.list_modal.modify_list": "Listeyi değiştir", + "scenes.apps.tasks.list_modal.new_list": "Yeni liste", + "scenes.apps.tasks.list_modal.remove": "Listeyi ve görevleri kaldır", + "scenes.apps.tasks.list_modal.predefined_participants": "Önceden tanımlanmış katılımcılar", + "scenes.apps.tasks.list_modal.archive_all_tasks": "Tüm görevleri arşivle", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "Arşivlenmiş görevleri kaldırın ({{$1}})", + "scenes.login.footer.go_to_twake": "twakeapp.com'a gidin", + "scenes.login.footer.branding": "Bir {{$1}} ({{$2}}) özel Twake sunucusundasınız. ", + "scenes.login.create_account.title": "Yeni bir hesap oluştur", + "scenes.login.create_account.email": "e-posta", + "scenes.login.create_account.email_used": "Bu e-posta zaten kullanılıyor.", + "scenes.login.create_account.username": "Kullanıcı adı", + "scenes.login.create_account.username_already_exist": "Bu kullanıcı adı zaten kullanılıyor", + "scenes.login.create_account.fill_in_username": "Kullanıcı adınızı doldurmalısınız", + "scenes.login.create_account.fill_in_email": "E-postanızı doğru bir e-posta ile doldurmalısınız", + "scenes.login.create_account.too_short_password": "Şifreniz en az 8 karakter içermelidir.", + "scenes.login.create_account.firstname": "İlk adı", + "scenes.login.create_account.newsletter": "Twake hakkında bilgi alın", + "scenes.login.create_account.lastname": "Soyadı", + "scenes.login.forgot_password.title": "Parolanızı mı unuttunuz?", + "scenes.login.forgot_password.text": "Kimliğinizi doğrulamak için e-posta ile 9 haneli bir kod alacaksınız.", + "scenes.login.forgot_password.email_to_recover": "Kurtarmak için e-posta", + "scenes.login.forgot_password.mail_doesnt_exist": "Bu e-posta mevcut değil", + "scenes.login.forgot_password.text2": "9 haneli bir kod alacaksınız. Devam etmek için lütfen aşağıdaki alana giriniz.", + "scenes.login.forgot_password.invalid_code": "Bu kod geçerli değil.", + "scenes.login.forgot_password.text3": "Hesabınız için yeni bir şifre girin.", + "scenes.login.forgot_password.password": "Parola", + "scenes.login.forgot_password.password2": "Şifreyi Onayla", + "scenes.login.forgot_password.password_dont_match": "Şifreleriniz uyuşmuyor veya çok kısa. Lütfen en az 8 karakterden oluşan bir şifre giriniz.", + "scenes.login.home.title": "Twake'te oturum açın", + "scenes.login.home.subtitle": "Seni gördüğüme sevindim", + "scenes.app.popup.appsparameters.pages.alert_published_app": "Başvurunuz yayınlandı, düzenleyemezsiniz.", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "Tüm IP adreslerine izin vermek için geliştirme aşamasında * kullanın.", + "scenes.app.popup.appsparameters.pages.api_data_description": "Twake API için faydalı veriler.", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "Bekleniyor...", + "scenes.app.popup.appsparameters.pages.website_label": "İnternet sitesi", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "Yazma ayrıcalıkları", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "Yayınlanırsa bu uygulamayı silemezsiniz.", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "Uygulama güncellenirken bir hata oluştu.", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "Uygulamaları ara", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "Bu çalışma alanının uygulamaları", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "Aramaya dön", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "Kullanıcıları davet et", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "Kullanıcılar", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "Entegrasyonlar", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "Okuma erişimi", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "Tüm şirketten çıkar", + "scenes.apps.calendar.day_option": "Gün", + "scenes.apps.calendar.modals.event_description_placeholder": "Açıklama", + "scenes.apps.calendar.modals.event_title_placeholder": "Başlık", + "scenes.apps.calendar.modals.modify_event_button": "Etkinliği düzenle", + "scenes.apps.calendar.modals.part.participants": "Katılımcılar", + "scenes.apps.drive.no_storage_app_alert": "Harici depolama eklemenize izin veren uygulamanız yok.", + "scenes.apps.drive.remove_definitely_menu": "Kalıcı olarak sil", + "scenes.apps.drive.restore_menu": "Onarmak", + "scenes.apps.drive.throw_menu": "çöp kutusuna gönder", + "scenes.apps.drive.trash_empty_menu": "Boş çöp", + "scenes.apps.drive.unconfigured_tab": "Bu sekme henüz yapılandırılmamış.", + "scenes.apps.drive.viewer.edit_with_button": "{{$1}} ile düzenleyin", + "scenes.apps.drive.viewer.loading_preview_message": "Yükleniyor...", + "scenes.apps.messages.input.show_formatting": "Biçimlendirmeyi göster", + "scenes.tell_us": "Lütfen bize ne yaptığınızı söyleyin:", + "scenes.apps.drive.viewer.download_desktop": "Uygulamada önizlemek için Twake Desktop'ı indirin", + "scenes.apps.tasks.my_tasks": "Görevlerim", + "scenes.apps.tasks.board.place_holder": "Kurul adı", + "scenes.apps.tasks.board.tasks.subtask": "alt görev", + "scenes.apps.tasks.board.tasks.add_subtask": "Alt görev ekle", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "Kanaldan kaldır", + "components.leftbar.channel.workspaceschannels.menu.option_1": "Kanal oluştur", + "components.leftbar.channel.workspaceschannels.menu.option_2": "Bir kanala katılın", + "components.channelworkspacelist.title": "Kanallar", + "scenes.client.channelbar.workspacechannellist.autocomplete": "Kanal, kullanıcı veya doğrudan mesajları arayın", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "Yeni bir sekme oluştur", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "{{$1}}'i yeniden adlandır", + "components.connectorslistmanager.add_connectors": "Bağlayıcı ekle", + "components.upload.drop_files.toaster.error": "{{$1}} dosyadan fazlasını yükleyemezsiniz", + "components.emoji_picker.categories.frequently_used": "Sıklıkla kullanılan", + "components.emoji_picker.categories.smileys_and_people": "Suratlar ve İnsanlar", + "components.emoji_picker.categories.animals_and_nature": "Hayvanlar ve Doğa", + "components.emoji_picker.categories.food_and_drink": "Yiyecek içecek", + "scenes.login.home.email": "e-posta", + "scenes.login.home.unable_to_connect": "Geçersiz kimlik bilgileri", + "scenes.login.home.password": "Parola", + "scenes.login.home.login_btn": "Giriş yapmak", + "scenes.login.home.lost_password": "Parolanızı mı unuttunuz?", + "scenes.login.home.create_account": "Bir hesap oluşturun", + "scenes.login.create_account.password": "Parola", + "scenes.login.create_account.step_1_subtitle": "Daha basit olamazdı - sadece biraz bilgiye ihtiyacımız var.", + "scenes.login.create_account.step_2_subtitle_a": "Diğer kullanıcıların sizi tanıması için tam adınızı ekleyin.", + "scenes.login.create_account.step_2_subtitle_b": "Telefon numaranız gizli kalır.", + "scenes.login.create_account.step_3_mail_sent": "Size e-posta ile bir aktivasyon linki gönderdik.", + "scenes.login.create_account.step_3_subtitle": "Son adım — robot olmadığınızı doğrulamamız gerekiyor!", + "scenes.app.workspaces.create_company.company_name.placeholder": "Şirket Adı", + "scenes.app.workspaces.create_company.company_name.title_1": "Başlamak,", + "scenes.app.workspaces.create_company.company_name.title_2": "şirketinizin adını belirtin.", + "scenes.app.workspaces.create_company.default_workspace_name": "Ana", + "scenes.app.workspaces.create_company.importations.title_1": "Zaten dijital araçlarla mı çalışıyorsunuz? Araçlarınızı şimdi içe aktarın veya entegre edin!", + "scenes.app.workspaces.create_company.importations.title_2": "Endişelenme, bunu daha sonra yapabilirsin!", + "scenes.app.workspaces.create_company.invitations.title_2": "Ekibinize kullanıcılar ekleyin.", + "scenes.app.workspaces.create_company.title": "şirketimi oluştur", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "İkincil bir e-posta ekleyin", + "scenes.app.workspaces.welcome_page.added_to_company": "davet edildiniz ", + "scenes.app.workspaces.welcome_page.create_my_company": "şirketimi oluştur", + "scenes.app.workspaces.welcome_page.lets_go": "Hadi gidelim!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "Başka bir e-posta adresi kullanarak mı davet edildiniz?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Oh, peki... Görünüşe göre henüz kimse seni bir çalışma alanına davet etmemiş.", + "scenes.app.workspaces.welcome_page.ready_to_work": "Artık çalışmaya hazırsınız.", + "scenes.app.workspaces.welcome_page.see_you_soon": "Yakında görüşürüz!", + "scenes.app.workspaces.welcome_page.try_again": "Tekrar deneyin", + "scenes.app.workspaces.welcome_page.twake_team": "Uyandırmak", + "scenes.app.workspaces.welcome_page.welcome_header": "Twake'e hoş geldiniz!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "Hesabınıza birden fazla e-posta adresi bağlayabilirsiniz; size bildirim göndermek için yalnızca bir adres kullanılacaktır.", + "scenes.app.workspaces.welcome_page.main_mail_title": "ana adres", + "scenes.app.workspaces.welcome_page.other_mail_title": "ikincil adresler", + "scenes.app.workspaces.welcome_page.add_new_email": "E-posta ekle", + "scenes.app.workspaces.welcome_page.code_verification": "Doğrulama kodu", + "scenes.app.workspaces.welcome_page.new_email": "İkincil bir e-posta ekleyin", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "Size {{$1}} aracılığıyla bir doğrulama kodu gönderdik", + "scenes.app.workspaces.welcome_page.done": "bitirdim", + "scenes.login.forgot_password.finished": "Şifreniz başarıyla güncellendi.", + "scenes.apps.account.account.description_main": "Ana adresiniz, Twake'in bildirimlerinizi gönderdiği yerdir. İkincil adresleriniz, onları kullanan çalışma alanlarına otomatik olarak davet edilmenizi sağlar.", + "scenes.apps.account.account.emails.description": "Farklı e-posta adreslerinizi yönetin.", + "scenes.apps.account.account.make_main": "Ana ayarla", + "scenes.apps.account.account.password.description": "Şifreni değiştir.", + "scenes.apps.account.identity": "Kimlik", + "scenes.apps.account.identity.description": "Diğer Twake kullanıcıları tarafından görülebilen adınızı, soyadınızı ve profil resminizi değiştirin.", + "scenes.apps.account.preference": "tercihler", + "scenes.apps.account.thumbnail.max_weight": "Maksimum boyut 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "Bu e-postayı onaylayın", + "app.name.twake_calendar": "Takvim", + "app.name.twake_drive": "Belgeler", + "app.name.twake_tasks": "Görevler", + "components.calendar.repetition.everyday": "Günlük", + "components.calendar.repetition.does_not_repeat": "tekrar etmez", + "components.calendar.repetition.weekly_on": "Haftalık {{$1}}", + "components.calendar.repetition.monthly_on": "{{$1}} {{$2}} tarihinde aylık", + "components.calendar.repetition.monthly_on_day": "Aylık gün {{$1}}", + "components.calendar.repetition.annually_on": "{{$1}} tarihinde her yıl", + "components.calendar.repetition.every_weekday": "Hafta içi her gün (Pzt'den Cuma'ya)", + "components.calendar.repetition.custom": "Gelenek...", + "components.calendar.repetition.repeat": "Her tekrarla", + "scenes.app.channelsbar.currentuser.workspace_parameters": "Çalışma alanı ayarları", + "scenes.app.channelsbar.currentuser.logout": "oturumu Kapat", + "scenes.app.channelsbar.currentuser.update": "Güncelleme", + "scenes.app.channelsbar.currentuser.disable_notifications": "Devre dışı bırakmak", + "scenes.app.channelsbar.currentuser.disabling_notifications": "1 saat devre dışı bırak", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Sabah 9'a kadar devre dışı bırak yarın", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "yeniden etkinleştir", + "scenes.app.channelsbar.currentuser.user_parameter": "Bildirim ayarları", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "Bu çalışma alanını silmek istediğinizi onaylamak için lütfen aşağıya adı yazın ve sil tuşuna basın.", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "Bir kanala bağlanabilecek bağlayıcınız yok.", + "scenes.app.mainview.tabs.rename": "Yeniden isimlendirmek", + "scenes.app.popup.appsparameters.pages.app_modification_right": "Bu şirketin tüm yöneticileri bu uygulamayı düzenleyebilecek.", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "Uygulamanızın neleri düzenleyebileceğini ve okuyabileceğini tanımlayın.", + "scenes.app.popup.appsparameters.pages.automatique_label": "Otomatik", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "'Otomatik' seçeneğini etkinleştirirseniz, bu uygulama bu şirketin sonraki çalışma alanlarına otomatik olarak eklenecektir.", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "İzin verilen IP adresleri", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "Başvurunuzun yayınlanması şu anda Twake ekibi tarafından onaylanmayı bekliyor.", + "scenes.app.popup.appsparameters.pages.button_force": "Şirket genelinde kuvvet", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "tehlikeli bölge", + "scenes.app.popup.appsparameters.pages.description_label": "Açıklama", + "scenes.app.popup.appsparameters.pages.error_check_needed": "Bir hata oluştu; bilgilerinizi kontrol edin.", + "scenes.app.popup.appsparameters.pages.error_message": "Bu ad zaten başka bir uygulama tarafından kullanılıyor; Lütfen başka birini seçiniz.", + "scenes.app.popup.appsparameters.pages.error_user_code": "hata", + "scenes.app.popup.appsparameters.pages.event_subtitle": "Olaylar", + "scenes.app.popup.appsparameters.pages.filter_information": "Bu filtre, API anahtarınızın kullanımını yalnızca bağlayıcınızdaki sunucularla sınırlar.", + "scenes.app.popup.appsparameters.pages.go_back": "Geri", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "Bu ad zaten başka bir uygulama tarafından kullanılıyor. Lütfen başka birini seçiniz.", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "basitleştirilmiş ad", + "scenes.app.popup.appsparameters.pages.installation": "yükleyin.", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "Mesajınızı JSON formatında yazarak başlayın.", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "Dahili uygulama", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "Yapılandırmanızı JSON biçiminde oluşturmak için belgelere gidin.", + "scenes.app.popup.appsparameters.pages.loading": "Yükleniyor...", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "Bir sonraki Etkinlikte gönderilecek olan pasif veriler", + "scenes.app.popup.appsparameters.pages.modify_public_data": "Uygulamanızın genel verilerini düzenleyin.", + "scenes.app.popup.appsparameters.pages.publication_label": "yayın", + "scenes.app.popup.appsparameters.pages.publish_app_label": "Uygulamayı yayınla", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "Okuma ayrıcalıkları", + "scenes.app.popup.appsparameters.pages.remove_app": "{{$1}} uygulamasını kalıcı olarak silin.", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "Tüm şirketten çıkar", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "Çalışma alanından kaldır", + "scenes.app.popup.appsparameters.pages.show_button": "Göstermek", + "scenes.app.popup.appsparameters.pages.status_tilte": "Durum", + "scenes.app.popup.appsparameters.pages.remove_app_button": "Uygulamayı sil", + "scenes.app.popup.appsparameters.pages.update_button": "Güncelleme", + "scenes.app.popup.createworkspacepage.add_subtitle": "Daha fazla alana ihtiyaç var?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "Yeni bir çalışma alanı oluşturun", + "scenes.app.popup.createworkspacepage.placeholder_name": "Çalışma alanının adı", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "Mobil bildirimlerin sıklığını ayarlayın.", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "Bildirimlerin sıklığı", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "Özel mesaj içeriğini gizle", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "Bildirim almayacağınız bir dönem seçin.", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "geceleri rahatsız etmeyin", + "scenes.app.popup.userparameter.pages.notif_content_label": "Bildirimlerin içeriği", + "scenes.app.mainview.quick_search_placeholder": "Hızlı arama", + "scenes.app.popup.userparameter.personnal_workspaces_title": "Çalışma alanlarınız", + "scenes.app.popup.workspaceparameter.admin_current_status": "Siz bir Yöneticisiniz.", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "Siz bir çalışma alanı yöneticisisiniz.", + "scenes.app.popup.workspaceparameter.manager_current_status": "Siz bir şirket yöneticisisiniz.", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "Çalışma alanını sil", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "Kaldırmak için çalışma alanında yalnız olmalısınız. Ortak çalışanlarınızı kaldırın ve tekrar deneyin.", + "scenes.app.popup.workspaceparameter.pages.enter": "Girmek ", + "scenes.app.popup.workspaceparameter.pages.access_apps": "Uygulamalarınıza ve bağlayıcılarınıza erişin", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "Çalışma alanı moderatörü", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "Şirketin diğer alanlarında kurulu uygulamalar {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "Yüklü uygulamalar", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "Aşağıdaki kullanıcılar davet edilirken bir hata oluştu: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "Kullanılan kullanıcı adının veya e-postanın geçerli olup olmadığını kontrol edin.", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "Bu çalışma alanının görüntüsünü düzenleyin", + "scenes.app.popup.workspaceparameter.pages.research_by": "Uygulamaları ada ve kategorilere göre arayın", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "Uygulamaları ara...", + "scenes.app.popup.workspaceparameter.pages.show_button": "Görüntülemek", + "scenes.app.popup.workspaceparameter.pages.title": "Çalışma alanı ayarları", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "Web kancalarına erişim", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "Maksimum boyut 5 MB.", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "Bu çalışma alanından kaldır", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "çalışma alanı", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "Yazma erişimi", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "Uygulamalarınız", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} ayarları", + "scenes.apps.calendar.add_calendar_menu": "Takvim ekle", + "scenes.apps.calendar.connectors_menu": "Konektörler...", + "scenes.apps.calendar.connectors_search_menu": "Bağlayıcı ara...", + "scenes.apps.calendar.create_calendar_title": "Bir takvim oluşturun", + "scenes.apps.calendar.edit_calendar_title": "Takvimi düzenle", + "scenes.apps.calendar.export_title": "İhracat", + "scenes.apps.calendar.export_view_menu": "Görünümü dışa aktar...", + "scenes.apps.calendar.ics_download_menu": "Bir ICS dosyası indirin", + "scenes.apps.calendar.ics_subscription_menu": "Bir ICS abonelik bağlantısı alın", + "scenes.apps.calendar.modals.advanced_options": "Gelişmiş seçenekler", + "scenes.apps.calendar.modals.description_placeholder": "Açıklama", + "scenes.apps.calendar.modals.details_title": "Detaylar", + "scenes.apps.calendar.modals.participants_event": "Katılımcılar", + "scenes.apps.calendar.modals.reminders": "hatırlatıcılar", + "scenes.apps.calendar.modals.remove_button": "Silmek", + "scenes.apps.calendar.modals.remove_event_button": "Etkinliği sil", + "scenes.apps.calendar.modals.remove_event_text": "Etkinlik silinsin mi?", + "scenes.apps.calendar.modals.title_placeholder": "Başlık", + "scenes.apps.drive.create_folder_button": "Oluşturmak", + "scenes.apps.drive.download_button": "İndirmek", + "scenes.apps.drive.open_link": "Bağlantıyı yeni pencerede aç", + "scenes.apps.drive.files_subtitle": "Dosyalar", + "scenes.apps.drive.folder_subtitle": "klasörler", + "scenes.apps.drive.go_out_trash_menu": "çöp bırak", + "scenes.apps.drive.go_trash_menu": "çöp kutusuna git", + "scenes.apps.drive.import_from_computer_menu": "bilgisayardan yükle", + "scenes.apps.drive.move_text": "Hareket", + "scenes.apps.drive.new_file_menu": "Yeni dosya", + "scenes.apps.drive.new_file_title": "Yeni dosya", + "scenes.apps.drive.new_external_storage": "Yeni harici depolama", + "scenes.apps.drive.new_folder_title": "Yeni dosya", + "scenes.apps.drive.viewer.no_preview_message": "Bu tür bir dosya görüntülenemiyor.", + "scenes.apps.messages.messageslist.go_last_message_button": "son mesaja git", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "Yeni mesajlar", + "services.user.update_password_alert": "Şifreniz güncellenmiştir.", + "scenes.apps.tasks.board.tasks.use_deadline": "Son tarihi kullan", + "scenes.apps.tasks.board.tasks.use_starttime": "Başlangıç zamanını kullan", + "scenes.apps.tasks.board.starts": "başlatır", + "scenes.apps.tasks.board.ends": "için yapılacak", + "scenes.apps.tasks.board.list_name": "Liste adı", + "scenes.app.popup.sync_calendar": "Takvimlerinizi senkronize edin.", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "şirket logosu", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "Şirket resmini düzenle ", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "daveti iptal et", + "scenes.apps.account.account.fullname": "Ad Soyad", + "login.email_login": "E-posta / Giriş", + "scenes.apps.account.account.password_for_user": "Kullanıcınız için şifre", + "scenes.apps.account.account.send_info": "Bu kimlik bilgilerini kullanıcınıza gönderin.", + "scenes.apps.account.account.save": "Hesabı kaydet", + "scenes.apps.account.message_temporary": "Geçici bir hesap, normal bir Twake hesabı gibi çalışır, ancak parolayı siz oluşturursunuz ve gerekirse parolayı sıfırlayabilirsiniz.", + "scenes.apps.account.message_user_signin": "Kullanıcınız bu aynı e-postayı kullanarak herhangi bir zamanda oturum açabilir ve geçici hesabı normal bir hesapla değiştirebilir.", + "scenes.app.mainview.link_expired": "Bu genel bağlantı geçersiz veya süresi dolmuş.", + "scenes.app.mainview.create_account": "üzerinde ücretsiz olarak çalışma alanınızı oluşturun ", + "scenes.apps.calendar.modals.reminder_add": "Hatırlatıcı ekle", + "components.attachmentpicker.add_attachment": "Ek ekle", + "components.drive.new_versions": "Yeni bir sürüm ekle", + "components.drive.navigators.directory_not_found": "Dizin bulunamadı.", + "components.drive.right_preview.suppress_link": "Bağlantıyı bastır", + "components.tagpicker.tag_name": "Etiket adı", + "components.upload.drop_files": "Dosyalarınızı buraya bırakın", + "components.workspace.list_manager.no_workspace": "Çalışma alanı yok", + "components.workspace.list_manager.add": "Çalışma alanları ekle", + "components.workspace.list_manager.current_space": "Geçerli çalışma alanı", + "components.workspace.list_manager.current_company": "Mevcut şirket", + "components.workspace.list_manager.all": "Tüm", + "components.workspace.calendar.invalid": "Geçersiz", + "components.searchpopup.enter_text": "Twake'i aramak için bir metin girin.", + "components.searchpopup.loading": "Daha fazla sonuç yükleniyor", + "components.searchpopup.filter_ws": "Çalışma alanlarını filtrele", + "components.searchpopup.tags": "Etiketler", + "components.searchpopup.size": "Boy", + "components.searchpopup.creation": "oluşturma", + "components.searchpopup.update_search": "Aramayı güncelle", + "components.searchpopup.last_modif": "Son değişiklik", + "components.searchpopup.sender": "Gönderen", + "components.searchpopup.mentions": "Mansiyonlar", + "components.searchpopup.only_pinned": "Yalnızca sabitlenmiş mesajlar", + "components.alert.confirm": "İşleminizi onaylayın", + "components.alert.confirm_click": "Tamam'a tıklayarak işleminizi onaylayın.", + "components.searchpopup.tasks": "Görevler", + "scenes.app.mainview.advanced_search_placeholder": "Gelişmiş Arama", + "components.searchpopup.hide_filters": "filtreleri gizle", + "components.searchpopup.show_filters": "filtreleri göster", + "components.searchpopup.load_more": "Daha fazla sonuç yükle", + "general.more": "Daha", + "scenes.apps.board.archived_tasks": "Arşivlenmiş görevler ({{$1}})", + "scenes.apps.board.active_tasks": "Aktif görevler", + "scenes.apps.board.kanban": "kanban", + "scenes.apps.board.display_as": "olarak göster", + "scenes.apps.board.new_task": "+ Yeni görev", + "scenes.apps.board.all_boards": "Tüm Panolar", + "components.userlistmanager.no_users": "Kullanıcı yok.", + "scenes.apps.calendar.video_link": "Bağlantıyı açmak için tıklayın", + "components.tagpicker.notag": "Etiket yok", + "scenes.apps.tasks.modals.attachments": "ekler", + "components.calendar.calendarselector.from": "İtibaren", + "scenes.apps.drive.move_text2": "Hareket", + "components.attachmentpicker.from_computer": "cihazınızdan", + "components.attachmentpicker.from_twake": "Twake Belgelerinden", + "components.attachmentpicker.file": "Dosya", + "components.attachmentpicker.remove_attach": "Eki kaldır", + "scenes.apps.drive.remove_attachs": "Ekleri kaldır", + "components.drive.elements.see": "Görmek", + "components.drive.elements.current_name": "Şu anki ismi: ", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "Tartışmayı gizle", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} e-posta(lar)ı eklenecek", + "components.newversion.new_version_component.row.part_1": "Eski bir Twake sürümü çalıştırıyorsunuz", + "components.newversion.new_version_component.row.part_2": "Uygulamayı yeniden yüklemenizi ve yeni özelliklerimizin keyfini çıkarmanızı öneririz!", + "components.newversion.new_version_component.link": "Yeniden yüklemek için burayı tıklayın", + "components.newversion.new_version_modal.title": "Yeni güncelleme mevcut !", + "scenes.apps.drive.download_all_button": "Hepsini indir", + "components.inputs.input_with_select.input.placeholder": "Kanal ismi", + "components.inputs.input_with_select.select.placeholder": "Bölüm adı", + "components.inputs.input_with_select.select.no_sections": "İlk kanal bölümünüzün adını yazmaya başlayın.", + "components.inputs.input_with_select.button.tooltip": "Bir kanal bölümü ayarla", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}}, kanala {{$2}} ekledi", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}}, {{$2}}'i kanaldan kaldırdı", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} bir konektörü çıkardı {{$2}}", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Daha fazla yükle", + "general.verify": "Doğrulamak", + "components.unverified_account.typography_text_danger": "Deneme sürenizde {{$1}} gününüz kaldı. Deneme hesabı 7 gün sonra bloke edilecek ve 1 aylık kayıttan sonra kalıcı olarak silinecektir. Size gönderdiğimiz doğrulama e-postasındaki \"Hesabımı doğrula\" butonuna tıklayarak hesabınızı doğrulayabilirsiniz.", + "components.unverified_account.verification_details": "Doğrulama ayrıntılarını şu adrese gönderdik:", + "components.account_verification_status_sentence": "Hesap durumunuz: {{$1}}", + "components.unverified_account.re_send_email": "E-postayı almadınız mı?", + "components.blocked_account.trial_period_over": "Deneme süreniz bitti. Hesabınızın kilidini açmak ve tüm işlevlere erişmek için lütfen hesabınızı e-posta onayı ile doğrulayın.", + "components.add_mails_workspace.button": "Twake'i kullanmaya başlayın", + "components.add_mails_workspace.title_1": "Bazı kullanıcılar ekle", + "components.add_mails_workspace.title_2": "Twake bir ekip işbirliği aracıdır, bu nedenle bazı kullanıcıları sizin için oluşturduğumuz bir çalışma alanını test etmeye davet edin.", + "components.add_mails_workspace.text_area_placeholder": "Kullanıcılarınızın e-postalarını girin*", + "components.verify_mail.title_1": "Tebrikler", + "components.verify_mail.title_2": "Artık resmi bir Twake kullanıcısısınız!", + "components.verify_mail.button": "Kullanıcı Ekle", + "components.verify_mail.text": "Her şeyden önce, e-posta adresinizi doğrulamanız gerekir. Şu adrese bir doğrulama bağlantısı gönderdik:", + "components.verify_mail.paragraph": "İsterseniz bunu daha sonra yapabilirsiniz ancak doğrulanmamış hesapların Twake'in yalnızca sınırlı bir sürümüne erişimi vardır.", + "services.console_services.toaster.add_emails_error": "E-posta(lar) eklenirken hata oluştu", + "services.console_services.toaster.add_email_error_message": "{{$1}} eklenirken hata oluştu", + "services.console_services.toaster.success_verify_email": "E-posta hesabınıza bir doğrulama bağlantısı gönderildi", + "scenes.app.popup.workspaceparameter.edit_from_console": "Konsolda Gör", + "services.console_services.toaster.success_invite_emails": "{{$1}} kullanıcı(lar) başarıyla eklendi", + "scenes.client.channels_bar.modals.guest_management.title": "Misafirleri {{$1}} içinde yönetin", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "Misafirleri veya bekleyen e-postaları arayın", + "scenes.client.channels_bar.modals.guest_management.tips": "Yukarıdaki girişi kullanarak e-posta eklemeye veya aramaya başlayın", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "Mail gönderildi", + "general.user.role.company.admin": "şirket yöneticisi", + "general.user.role.company.member": "Üye", + "general.user.role.company.guest": "Konuk", + "general.user.deleted": "Silinen Hesap", + "components.richtexteditor.toolbar.bold": "Gözü pek", + "components.richtexteditor.toolbar.underline": "Altını çizmek", + "components.richtexteditor.toolbar.italic": "İtalik", + "components.richtexteditor.toolbar.strikethrough": "üstü çizili", + "components.richtexteditor.toolbar.code": "kod", + "components.richtexteditor.toolbar.unordered-list": "Maddeli liste", + "components.richtexteditor.toolbar.ordered-list": "Sıralı Liste", + "components.richtexteditor.toolbar.blockquote": "blok alıntı", + "components.richtexteditor.toolbar.code-block": "Kod Bloğu", + "components.locked_features.locked_history_banner.title": "Az önce mesaj sınırına ulaştınız", + "components.locked_features.locked_history_banner.button": "Daha fazla bilgi edin", + "components.on_boarding.popups.blocked_company.or": "Veya", + "components.on_boarding.popups.blocked_company.company_selector": "Başka bir şirkete geç", + "scenes.apps.tasks.select_user_button": "Başka bir kullanıcı için görevleri görüntüleyin", + "scenes.apps.tasks.select_user": "Kullanıcı ara", + "scenes.apps.messages.input.attach_file.from_computer": "bilgisayardan", + "scenes.app.popup.workspaceparameter.pages.table_title": "İsim", + "scenes.client.main_view.main_header.search_input": "Arama", + "scenes.apps.drive.new_link_title": "Yeni bağlantı", + "scenes.apps.drive.default_link_name": "başlıksız", + "components.emoji_picker.input_search_placeholder": "Arama", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - Bir mesaja {{$2}}'ten fazla dosya ekleyemezsiniz", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "Bu mesajı sildin", + "general.uploading": "yükleniyor", + "components.emoji_picker.categories.activity": "Aktivite", + "components.emoji_picker.categories.travel_and_places": "Seyahat ve Yerler", + "components.emoji_picker.categories.objects": "nesneler", + "components.emoji_picker.categories.symbols": "semboller", + "components.emoji_picker.categories.flags": "Bayraklar", + "components.emoji_picker.categories.search_result": "Arama Sonuçları", + "components.emoji_picker.categories.not_found": "Emoji Bulunamadı", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "rol", + "general.email": "E-posta", + "components.locked_features.locked_only_office_popup.title": "Bu dosyayı düzenleyemezsiniz", + "components.locked_features.locked_only_office_popup.text": "Hata!! Dosyayı Twake'den düzenlemek istiyor gibisiniz. Ofis dosyaları etrafında işbirliği yapmak istiyorsanız planınızı yükseltmeyi düşünebilirsiniz. Fiyatlandırma seçeneklerimizi keşfedin ve ekip işbirliği ihtiyaçlarınız için en iyi seçeneği belirleyin.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Çalışma alanına davet bağlantısı", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Yeni bağlantı oluşturuldu", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Panoya başarıyla kopyalandı", + "scenes.app.popup.adduser.magiclinks.action_copy": "kopyala", + "scenes.app.popup.adduser.magiclinks.action_generate": "üret", + "scenes.apps.calendar.modify_calendar_menu": "Takvimi düzenle", + "scenes.apps.calendar.month_option": "Ay", + "scenes.apps.calendar.my_calendar": "Takvimim", + "scenes.apps.calendar.my_calendar_label": "Takvimim", + "scenes.apps.calendar.my_calendar_menu": "Takvimim", + "scenes.apps.drive.choose_folder_button": "Bir dizin seçin", + "scenes.apps.drive.choose_file_button": "Bir dosya seçin", + "scenes.apps.drive.viewer.open_with_button": "Bununla aç...", + "scenes.apps.messages.input.placeholder": "Bir mesaj yaz. Bir kullanıcıdan alıntı yapmak için @ kullanın.", + "components.drive.elements.configurate_mod": "Modu yapılandırın...", + "components.drive.elements.manage_version": "Sürümleri yönet", + "scenes.app.popup.createcompany.try_again": "Lütfen tekrar deneyin.", + "scenes.app.popup.workspace.edit_temp": "Geçici hesabı düzenle", + "scenes.app.popup.workspace.create_temp": "Geçici hesap oluştur", + "scenes.apps.tasks.active_tasks": "aktif görevler", + "scenes.apps.drive.right_preview.versions": "Sürümler", + "scenes.app.popup.appsparameters.pages.icon": "Simge", + "components.locked_features.locked_history_banner.description": "Şirketinizin çok fazla mesajı var! Tüm mesaj geçmişinize erişmek için şimdi yükseltin.", + "components.locked_features.locked_guests_popup.title": "Misafirler özelliği kilitli", + "components.locked_features.locked_guests_popup.description": "Hata!! Görünüşe göre harici kullanıcıları çalışma alanınıza davet etmek istiyorsunuz. Misafirler ve harici ortaklarla işbirliği yapmak istiyorsanız planınızı yükseltmeyi düşünebilirsiniz. Fiyatlandırma seçeneklerimizi keşfedin ve ekip işbirliği ihtiyaçlarınız için en iyi seçeneği belirleyin.", + "components.locked_features.locked_guests_popup.learn_more_button": "Daha fazla bilgi edin", + "components.locked_features.locked_guests_popup.skip_for_now_button": "Şimdilik geç", + "components.locked_features.locked_guests_popup.or": "Veya", + "components.on_boarding.popups.blocked_company.description": "Twake aboneliğinizin süresi doldu. Yenilemek ve ekibinizle tekrar iletişim kurabilmek için lütfen şirketinizin sahibi veya yöneticisi ile iletişime geçin!", + "components.on_boarding.popups.blocked_company.learn_more_text": "Şirket abonelik planı hakkında daha fazla bilgi edinmek ister misiniz?", + "components.locked_features.locked_workspace_popup.text": "Hata!! Şirketinizde yeni bir çalışma alanı mı yaratmak istiyorsunuz? Planınızı yükseltmeyi düşünebilirsiniz. Fiyatlandırma seçeneklerimizi keşfedin ve ekip işbirliği ihtiyaçlarınız için en iyi seçeneği belirleyin.", + "scenes.app.integrations_parameters.company_application_popup.tag": "Kurulmuş", + "scenes.app.integrations_parameters.company_application_popup.btn": "Düzenlemek", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "bilgiler", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "Açıklama", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Göstermek", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "şirketten uzaklaştır", + "scenes.app.integrations_parameters.company_applications_table.name": "İsim", + "scenes.app.integrations_parameters.company_applications_table.title": "Şirketinizde yüklü", + "scenes.join.loading": "Yükleniyor…", + "scenes.join.wrong_link_title": "Bu bağlantı artık mevcut değil", + "scenes.join.wrong_link_description": "Sizi bu şirkete katılmaya davet eden kişiden yeni bir bağlantı isteyin veya kendi şirketinizi oluşturun", + "scenes.join.create_the_company_button": "şirket oluştur", + "scenes.join.join_workspace_from_company": "{{$2}}'ten {{$1}}'e katılın!", + "scenes.join.twake_description": "Twake, ekip üretkenliğinizi artırmak için oluşturulmuş açık kaynaklı bir dijital çalışma alanıdır.", + "components.user_picker.modal_no_result": "Sonuç bulunamadı", + "components.users_picker.add_me": "beni ekle", + "scenes.app.workspaces.create_company.invitations.title": "Çalışma alanınızı yapılandırın.", + "scenes.app.header.disconnected": "bağlantınız kesildi", + "scenes.app.header.disconnected.reload": "Tekrar yükle", + "scenes.app.header.alt_notifications": "Bildirimler", + "scenes.apps.calendar.calendar.week_btn": "Hafta", + "scenes.apps.calendar.calendar.list_btn": "Liste", + "scenes.apps.calendar.event_edition.deadline_tag": "Son teslim tarihi", + "scenes.apps.calendar.event_edition.checkbox_all_day": "Tüm gün", + "scenes.apps.calendar.event_edition.title_confidentiality": "Gizlilik", + "scenes.apps.calendar.event_view.article_until": "ile", + "scenes.apps.calendar.calendar_modal.participants": "Katılımcılar", + "scenes.apps.calendar.calendar_modal.placeholder": "İsim", + "scenes.apps.calendar.left.calendars": "Takvimler", + "scenes.apps.drive.left.search": "Arama", + "scenes.apps.drive.navigators.navigator_content.directory_name": "dizin adı", + "scenes.apps.drive.navigators.navigator_content.files": "Dosyalar", + "scenes.apps.drive.navigators.navigator_labels.title": "Etiketler", + "scenes.apps.drive.navigators.new_file.untitled": "başlıksız", + "scenes.apps.drive.navigators.new_file.create_file.type": "Tip", + "scenes.apps.drive.navigators.new_file": "Yeni dosya", + "scenes.apps.drive.preview_bloc.operations_download": "İndirmek", + "scenes.apps.drive.preview_bloc.error_file": "Dosya bulunamadı", + "scenes.apps.drive.right_preview.operations_restore": "Onarmak", + "scenes.apps.drive.right_preview.operations_delete": "Çöp kutusuna taşıyın", + "scenes.apps.drive.right_preview.public_link": "Herkese açık bağlantı", + "scenes.apps.messages.messages": "Mesajlar", + "scenes.apps.messages.chatbox.chat.delete_message": "Bu mesajı sil", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "Mesajı sil", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "İsim", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "Favorilere ekle", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "Favorilerden çıkar", + "scenes.apps.messages.left_bar.stream.notifications": "Bildirimler...", + "scenes.apps.messages.left_bar.stream.notifications.all": "herhangi bir mesaj", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}, {{$2}} ve {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "sadece {{$1}}", + "scenes.apps.messages.left_bar.stream.notifications.never": "Hiçbir şey değil", + "scenes.apps.parameters.workspace_sections.workspace": "çalışma alanı", + "scenes.apps.parameters.workspace_sections.members": "Katılımcılar", + "scenes.apps.parameters.group_sections.workspaces": "çalışma alanları", + "scenes.apps.parameters.group_sections.apps": "uygulamalar", + "scenes.apps.account.languages.text": "Twake dilini değiştirin.", + "components.calendar.repetition.ends": "biter", + "scenes.apps.tasks.boards": "Panolar", + "scenes.apps.tasks.connectors_menu": "Konektörler...", + "scenes.apps.tasks.connectors_search_menu": "Bağlayıcı ara...", + "scenes.apps.tasks.no_connectors_menu_text": "Bir takvime bağlanabilecek bağlayıcınız yok.", + "scenes.apps.tasks.unconfigured_tab": "Bu sekme henüz yapılandırılmamış.", + "scenes.apps.tasks.choose_board_button": "Bir tahta seçin", + "general.open": "Açık", + "components.calendar.repetition.never": "Hiçbir zaman", + "components.calendar.repetition.on": "Açık", + "components.calendar.repetition.after": "Sonrasında", + "components.calendar.repetition.days": "gün(ler)", + "components.calendar.repetition.weeks": "haftalar)", + "components.calendar.repetition.months": "ay(lar)", + "components.calendar.repetition.years": "yıl(lar)", + "components.calendar.repetition.custom_recurrence": "Özel yineleme", + "components.calendar.repetition.occurrence": "Olay(lar)", + "components.calendar.repetition.repeat_on": "tekrarla", + "scenes.app.channelsbar.currentuser.add_apps": "Uygulamaları ara", + "scenes.app.channelsbar.currentuser.change_my_status": "durumumu değiştir", + "scenes.app.channelsbar.currentuser.collaborateurs": "Kullanıcılar", + "scenes.app.channelsbar.currentuser.create_workspace_page": "Bir çalışma alanı oluşturun", + "scenes.app.channelsbar.currentuser.invited_status": "sen misafirsin", + "scenes.app.channelsbar.currentuser.title": "Hesap ayarları", + "scenes.app.channelsbar.currentuser.workspace_info": "{{$2}} grubundan {{$1}} çalışma alanındasınız", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "FAVORİLER", + "scenes.app.channelsbar.channelsworkspace.create_channel": "Kanal oluştur", + "scenes.app.channelsbar.channelsworkspace.no_channel": "Henüz herhangi bir kanala katılmadınız", + "scenes.app.channelsbar.modify_channel_menu": "Kanalı düzenle", + "scenes.app.channelsbar.guest_management": "misafir yönetimi", + "scenes.app.channelsbar.read_sign": "Okundu olarak işaretle", + "scenes.app.channelsbar.unread_sign": "okunmamış olarak işaretle", + "scenes.app.channelsbar.channel_leaving": "kanaldan ayrıl", + "scenes.app.mainview.tabs.searching_connectors": "Bağlayıcı ara...", + "scenes.app.popup.adduser.adresses_message": "Lütfen adresleri virgül veya boşlukla ayırın. Twake'in aboneliğinize bağlı olarak davet sayısını sınırlayabileceğini unutmayın.", + "scenes.app.popup.appsparameters.pages._app_identity": "Uygulamanın kimliği", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "Twacode mesajlarınızın görünümünü test edin", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "benim harika uygulamam", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "Firmanın geliştirdiği uygulamalar", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "Uygulamanızın nerede görüneceğini belirlemenizi sağlar.", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "Görüntü ayarları", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "Logo", + "scenes.app.popup.workspaceparameter.pages.name_description": "Bu çalışma alanının adını değiştir", + "scenes.app.popup.workspaceparameter.pages.name_label": "Çalışma alanının adı", + "scenes.app.popup.workspaceparameter.pages.no_access": "Erişim yok.", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "Bu çalışma alanında uygulamanız yok", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "Bu çalışma alanından ayrıl", + "scenes.apps.calendar.modals.event_adresse_placeholder": "Adres", + "scenes.apps.drive.no_file_alert": "Dosya oluşturmanıza izin veren uygulamanız yok.", + "scenes.error_on_twake": "\"Bir problemimiz var Houston\"", + "scenes.help_us": "Ancak, bu hatayı düzeltmemize yardımcı olmak isterseniz, bize aşağıdan bir mesaj gönderin: ", + "scenes.login.verifymail.alert": "E-postanızı kontrol ediyoruz!", + "scenes.login.verifymail.error_message": "Bir hata oluştu", + "scenes.login.verifymail.signin_button": "Giriş yapmak", + "scenes.login.verifymail.success": "E-postanız başarıyla doğrulandı!", + "scenes.login.verifymail.verification_waiting": "Doğrulama bekleniyor...", + "scenes.no_panic": "Panik yapma! Twake'i düzeltmek için bu sayfayı yeniden yükleyin.", + "services.apps.calendar.deadline_icon": "Son teslim tarihi", + "services.apps.calendar.event_icon": "Etkinlik", + "services.apps.calendar.move_icon": "Hareket", + "services.apps.calendar.reminder_icon": "Hatırlatma", + "scenes.app.workspaces.components.skip": "Atlamak", + "scenes.apps.calendar.unconfigured_tab": "Bu sekme henüz yapılandırılmamış.", + "scenes.apps.drive.trash": "Çöp", + "scenes.apps.drive.top_menu_more": "Daha", + "scenes.apps.drive.top_menu_no_items": "{{$1}} öğeler", + "scenes.apps.messages.new_thread": "Yeni bir tartışma başlat", + "scenes.apps.messages.input.send_message": "Mesaj gönder", + "scenes.apps.messages.input.emoji": "emoji", + "scenes.apps.messages.input.hide_formatting": "Biçimlendirmeyi gizle", + "scenes.apps.tasks.board.tasks.in_list": "Listede", + "scenes.apps.parameters.workspace_sections.members.invite_all": "Tümünü davet et", + "scenes.app.taskpicker.select": "Seçme", + "components.listmanager.filter": "filtre", + "scenes.apps.tasks.no_connector": "Bağlayıcı yok", + "scenes.apps.drive.used": "Bu klasörde kullanılan", + "components.reminder.notification": "Bildirim", + "components.reminder.minutes_bef": "dakikalar önce", + "components.reminder.hours_bef": "saatler önce", + "components.reminder.days_bef": "Günler önce", + "components.reminder.weeks_bef": "haftalar önce", + "components.reminder.by_email": "E-Posta", + "components.alert.leave_private_channel.title": "Kanaldan ayrılmak istediğinizden emin misiniz?", + "components.alert.leave_private_channel.description": "Biri sizi davet etmedikçe bu özel kanala tekrar katılamazsınız.", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "üye değilsin", + "components.input.copied": "kopyalandı", + "scenes.client.channelbar.channelmemberslist.tag": "Sen", + "components.locked_features.locked_workspace_popup.title": "Daha fazla çalışma alanı oluşturamazsınız", + "components.locked_features.locked_workspace_popup.subtitle": "Ücretsiz sürümde, şirketinizde yalnızca bir çalışma alanınız olabilir.", + "scenes.app.workspaces.create_company.group_data.title": "Hızlı olacağız - sadece bazı istatistiksel bilgilere ihtiyacımız var.", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "Mesaj numarası", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "Twake'in ücretsiz sürümünde, daha yeni olan {{$1}} mesajlarından daha fazlasına erişemezsiniz.", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "Daha fazla plan göster", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "Yeni özel tartışma", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "Özel mesaj yok. Kullanıcıları davet edin!", + "scenes.app.channelsbar.channelsuser.private_messages": "Doğrudan mesajlar", + "scenes.app.channelsbar.channelsworkspace.channel_title": "KANALLAR", + "scenes.app.channelsbar.channel_removing": "Kanalı sil", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "Bu çerçeveye tıklayarak düzenli kalmak için bu kanalları işletmenize aktarabilirsiniz.", + "scenes.app.channelsbar.company_invitation_alert_title": "şirkete davetlisiniz ", + "scenes.app.channelsbar.initial_instructions_tutorial": "Bir ad, bir ad ve bir profil resmi seçin.", + "scenes.app.channelsbar.installation_desktop_tutorial": "Masaüstü uygulamasını yükleyin", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "Kullanıcıları çalışma alanınıza davet edin.", + "scenes.app.channelsbar.public_channel_label": "Halk", + "scenes.app.channelsbar.private_channel_label": "Özel", + "scenes.app.channelsbar.sending_message_instruction": "Bir tartışmada ilk mesajınızı gönderin", + "scenes.app.channelsbar.tutorial_alert": "Bu kareyi bir daha göstermeyecek misin?", + "scenes.app.channelsbar.welcome": "Twake'e hoş geldiniz", + "scenes.app.channelsbar.welcoming_message_subtitle": "Sadece birkaç tıklamayla Twake profesyoneli olun!", + "scenes.app.mainview.instruction_current_tab": "Solunuzda bir kanal seçerek başlayın.", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "API ayarları", + "scenes.app.popup.appsparameters.pages.app_name_label": "Uygulama Adı", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "Uygulama ayrıcalıkları", + "scenes.app.popup.appsparameters.pages.app_update": "Uygulamayı {{$1}} güncelleyin (uygulama {{$2}} kez kullanılır.)", + "scenes.app.popup.appsparameters.pages.application_title": "Başvuru", + "scenes.app.popup.appsparameters.pages.apps_title": "Uygulamalarınız ve bağlayıcılarınız", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "'{{$3}}' pasifleriyle '{{$1}}' türü ve '{{$2}}' kimliği olayı", + "scenes.app.popup.appsparameters.pages.company_label": "Şirket sahibi", + "scenes.app.popup.appsparameters.pages.configuration_label": "Yapılandırma", + "scenes.app.popup.appsparameters.pages.create_app_button": "Bir uygulama oluşturun", + "scenes.app.popup.appsparameters.pages.create_my_app": "Uygulamamı oluştur", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "Henüz bir uygulama oluşturmadınız. Bir uygulama veya bağlayıcı oluşturmadan önce, uygulama pazarımızda mevcut olmadığından emin olun.", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "Uygulamayı sil", + "scenes.app.popup.appsparameters.pages.new_app_title": "Yeni uygulama", + "scenes.app.popup.appsparameters.pages.ok_user_code": "Tamam", + "scenes.app.popup.appsparameters.pages.optimal_format": "En uygun biçim : 48x48 piksel.", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "Yayınlanmayan uygulama yalnızca şirketinizde çalışır. Tüm Twake kullanıcılarının kullanımına sunmak istiyorsanız, bu seçeneği etkinleştirin.", + "scenes.app.popup.appsparameters.pages.public_availability_application": "Genel uygulama", + "scenes.app.popup.appsparameters.pages.public_login_label": "Genel tanımlayıcı", + "scenes.app.popup.appsparameters.pages.publication_description": "Uygulamanızın görünürlüğünü belirleyin.", + "scenes.app.popup.appsparameters.pages.string_information": "Bu dize, uygulamanızı tanımlar ve mesaj komutlarında kullanılacaktır.", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode test cihazı", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "Etkinlik alma URL'si", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "Uygulamanızın basitleştirilmiş adı zaten başka bir uygulama tarafından kullanılıyor. Lütfen değiştirin.", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "Aşağıdaki anahtar kelimeleri vurgulayın:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "E-posta bildirimlerinin sıklığını ayarlayın.", + "scenes.app.popup.userparameter.pages.private_message_content.show": "Özel mesaj içeriğini göster", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "Son yönetici olduğunuz için çalışma alanından çıkamazsınız. Yeni bir yönetici tanımlayabilir veya bu çalışma alanını silebilir/arşivleyebilirsiniz.", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "Bütün uygulamalar", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "Şirketinizin uygulamaları", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "Firmanın geliştirdiği uygulamalar", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "Şirketin kimliği", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "Bu şirketin adını değiştir", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "Şirketin adı", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "yapılandırma", + "scenes.app.popup.workspaceparameter.pages.configure_button": "Yapılandır", + "scenes.app.popup.workspaceparameter.pages.description": "Açıklama", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "Firmanın geliştirdiği uygulamalar", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "Görüntüleme tercihleri", + "scenes.app.popup.workspaceparameter.pages.install_button": "Düzenlemek", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "Uygulamayı bu çalışma alanına yükleyin.", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "Bu çalışma alanında yüklü uygulamalar {{$1}}", + "scenes.apps.messages.messageslist.get_writing_users": "yazıyorlar...", + "components.drive.right_preview.create_link": "Bir erişim bağlantısı oluşturun", + "components.drive.moove_here": "Buraya taşın", + "components.drive.modify_uslist": "Kullanıcı listesini değiştir", + "scenes.apps.calendar.reminders": "hatırlatıcı(lar)", + "scenes.app.mainview.discussion": "Tartışma", + "scenes.client.channelbar.channelmemberslist.title": "{{$1}} içindeki kullanıcılar", + "scenes.client.channelbar.channelmemberslist.loader": "Daha fazla yükle", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Kullanıcı ekle veya ara", + "components.notifications.hidden_notifications_button.children": "Yeni mesajlar", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "Başvuru", + "scenes.client.channelbar.channelmemberslist.no_members": "Bu kanalda kullanıcı yok, Kullanıcı ekle'ye tıklayarak onları davet edebilirsiniz.", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} açıklamayı değiştirdi", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}}, kanalı {{$2}} olarak yeniden adlandırdı", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "{{$1}} yeni bir {{$2}} sekmesi ekledi {{$3}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}}, {{$2}} sekmesini kaldırdı {{$3}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} yeni bir bağlayıcı ekledi {{$2}}", + "general.re_send": "Yeniden gönder", + "components.account_verication_status_unverified": "Doğrulanmamış", + "components.account_verication_status_blocked": "Kilitli", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} mesajını sildi", + "components.member.user_parts.and_more_user_text": " ve {{$1}} daha fazla kullanıcı", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "Özel bir kanal oluşturun", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " Bunun yerine", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "10'dan fazla kullanıcı ekleyemezsiniz", + "components.locked_features.locked_drive_popup.title": "Az önce sürüş sınırına ulaştınız", + "components.locked_features.locked_drive_popup.subtitle": "Ücretsiz sürümde yalnızca 6 GB depolayabilirsiniz.", + "general.resume": "Devam et", + "general.pause": "Duraklat", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Henüz kimse sizi bir çalışma alanına davet etmedi.", + "'": "'", + "login.create_account": "Hesap oluştur", + "login.login_error": "Giriş sırasında hata", + "scenes.apps.messages.message.types.no_message_in_thread": "Henüz kimse cevap vermedi.", + "\"": "\"", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Varsayılan çalışma alanı", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Tüm çalışma alanı kullanıcılarını otomatik olarak bu kanala davet et", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "{{$1}} silmek üzeresiniz", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "{{$2}} içinde hala {{$1}} üyeniz var. Bu çalışma alanını silebilmek için tüm üyeleri kaldırmalısınız.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Çalışma alanımın tüm mesajlarının ve dosyalarının silineceğini anlıyorum.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Maksimum logo boyutu 5mb'dir", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Bozuk biçim, yalnızca png gif ve jpg'ye izin verilir", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Bilinmeyen hata", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Hata", + "scenes.app.channelsbar.currentuser.reset": "Sıfırla", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Kullanıcıları görüntülemek için en az üç harf yazın", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Kullanıcı bulunamadı", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Emoji bulunamadı", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Komut bulunamadı", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} yazıyor...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} ve {{$2}} yazıyor...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} ve {{$3}} daha fazla kullanıcı yazıyor...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Şirketiniz maksimum {{$1}} üye sınırına ulaştı. Lütfen ", + "components.locked_features_components.locked_invite_alert.message_link": "şirketini yükselt", + "components.locked_features_components.locked_invite_alert.message_part_2": " daha fazla üye davet etmek için.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " şirketinizin sahibi veya yöneticisiyle iletişime geçin.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Tüm şirket üyelerimi konsolda görün", + "scenes.app.popup.appsparameters.pages.app.private_key": "Özel anahtar", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Uygulamanızı birkaç kelimeyle tanımlayın", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Yeni entegrasyon", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Bu şirketin sahibi ve yöneticilerinin bu uygulamayı değiştirebileceğini ve yayınlayabileceğini anlıyorum.", + "twake.application.access.title": "Uygulamanız için doğru kapsamları seçin.", + "twake.application.access.no_default_scopes_available'": "Bu entegrasyon herhangi bir {{$1}} erişimine sahip değil", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake API belgeleri", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Bunları nasıl dolduracağınızı bilmiyorsanız, adresine gidin. ", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "{{$1}} uygulaması başarıyla kaldırıldı!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "{{$1}} uygulaması kaldırılırken hata oluştu!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Başarıyla {{$1}} uygulaması!", + "scenes.app.integrations_parameters.add_application": "Yeni entegrasyon", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Geliştirici ayarları", + "components.rich_text_editor.plugins.suggestions.loading": "daha fazlasını arıyorum", + "components.open_desktop_popup.subtitle": "Twake uygulamasında açıldı", + "components.open_desktop_popup.open_here_link": "Bunun yerine burada aç", + "molecules.download_banner.title": "Twake'den en iyi şekilde yararlanın, şimdi masaüstü uygulamasını indirin", + "molecules.download_banner.download_button": "Masaüstü uygulamasını indirin", + "scenes.app.channelsbar.channel_copy_link": "Kanal bağlantısını kopyala", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Başarıyla güncellendi", + "components.searchpopup.no_results_for": "için sonuç bulunamadı", + "components.searchpopup.try_new_search": "Yeni bir arama deneyin", + "components.searchpopup.all": "Herşey", + "components.searchpopup.chats": "sohbetler", + "components.searchpopup.media": "medya", + "components.searchpopup.files": "Dosyalar", + "components.searchpopup.recent_chats": "son sohbetler", + "components.searchpopup.recent_media": "son medya", + "components.searchpopup.recent_files": "Son Dosyalar", + "components.searchpopup.recent_channels_and_contacts": "Son kanallar ve kişiler", + "components.searchpopup.header_title": "Arama", + "components.searchpopup.scope.company": "tüm şirkette", + "components.searchpopup.scope.channel": "bu kanalda", + "components.searchpopup.channels": "Kanallar", + "components.searchpopup.messages": "Mesajlar" +} diff --git a/twake/frontend/public/locales/vi.json b/twake/frontend/public/locales/vi.json index 07aa3053d6..4f2a88dd25 100644 --- a/twake/frontend/public/locales/vi.json +++ b/twake/frontend/public/locales/vi.json @@ -316,7 +316,7 @@ "scenes.app.workspaces.create_company.importations.title_1": "Đã từng làm việc với công cụ số? Nhập hoặc tính hợp công cụ của bạn ngay bây giờ!", "scenes.app.workspaces.create_company.title": "Tạo công ty của tôi", "scenes.app.workspaces.welcome_page.add_secondary_emails": "Thêm thư điện tử phụ", - "scenes.app.workspaces.welcome_page.no_company_subtitle": "Ôi, được rồi... Dường như bạn chưa được mời vào một không gian làm việc nào cả.", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "Ôi, được rồi... Dường như bạn chưa được mời vào một công ty nào cả.", "scenes.app.channelsbar.currentuser.user_parameter": "Cài đặt thông báo", "scenes.app.channelsbar.currentuser.reactivate_notifications": "Kích hoạt lại", "scenes.app.channelsbar.currentuser.disabling_notifications_until": "Vô hiệu đến 9 giờ sáng hôm sau", @@ -497,7 +497,7 @@ "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} đã xóa một liên kết {{$2}}", "components.alert.leave_private_channel.title": "Bạn có chắc chắn là muốn rời bỏ kênh?", "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "Tải thêm", - "components.unverified_account.verification_details": "Chúng tôi đã gửi cho bạn thông tin xác minh chi tết đến", + "components.unverified_account.verification_details": "Chúng tôi đã gửi cho bạn một thư xác minh thông tin đến", "components.account_verification_status_sentence": "Trạng thái tài khoản của bạn là: {{$1}}", "components.account_verication_status_blocked": "Khóa", "components.add_mails_workspace.title_1": "Thêm vài người dùng", @@ -548,7 +548,7 @@ "scenes.app.popup.appsparameters.pages.smalltext_group_id": "Mã định danh nhóm hiện tại", "scenes.client.channelbar.channeltemplateeditor.checkbox": "Tự động mời toàn bộ thành viên không gian làm việc vào kênh này", "scenes.client.channelbar.channelmemberslist.title": "Người dùng trong {{$1}}", - "scenes.client.channelbar.channelmemberslist.autocomplete": "Thêm hoặc tìm kiếm người dùng", + "scenes.client.channelbar.channelmemberslist.autocomplete": "Tìm kiếm người dùng", "scenes.client.channelbar.channelmemberslist.menu.option_2": "Xóa khỏi kênh", "components.leftbar.channel.workspaceschannels.menu.option_1": "Tạo một kênh", "components.leftbar.channel.workspaceschannels.menu.option_2": "Tham gia kênh", @@ -739,7 +739,7 @@ "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} đã xóa {{$2}} tab {{$3}}", "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "Bạn không phải là thành viên", "general.verify": "Xác thực", - "components.unverified_account.typography_text_danger": "Bạn còn {{$ 1}} ngày trong thời gian dùng thử. Tài khoản dùng thử sẽ bị khóa sau 7 ngày và xóa vĩnh viễn sau 1 tháng đăng ký. Bạn có thể xác minh tài khoản của mình bằng cách nhấp vào nút \"Xác minh tài khoản của tôi\" trong email xác minh mà chúng tôi đã gửi cho bạn.", + "components.unverified_account.typography_text_danger": "Hãy xác minh tài khoản trong vòng {{$ 1}} ngày. Tài khoản dùng thử sẽ bị khóa sau 7 ngày và xóa vĩnh viễn sau 1 tháng đăng ký. Bạn có thể xác minh tài khoản của mình bằng cách nhấp vào nút \"Xác minh tài khoản của tôi\" trong email xác minh mà chúng tôi đã gửi cho bạn.", "scenes.app.popup.workspaceparameter.edit_from_console": "Xem trong bảng điều khiển", "components.on_boarding.popups.blocked_company.description": "Gói đăng ký Twake của bạn hết hạn. Hãy liên hệ với chủ sở hữ công ty hoặc quản trị viên để kiểm tra và để tiếp tục có thể trao đổi với nhóm của bạn!", "components.richtexteditor.toolbar.underline": "Gạch chân", @@ -771,5 +771,140 @@ "components.locked_features.locked_drive_popup.subtitle": "Ở gói miễn phí, bạn chỉ có thể lưu trữ tối đa 6GB.", "scenes.apps.drive.no_file_alert": "Bạn không có ứng dụng nào để có thể cấp quyền tạo tệp.", "components.alert.confirm": "Xác nhận hành động của bạn", - "components.locked_features.locked_workspace_popup.text": "Whoops!!Bạn muốn tạo thêm không gian làm việc mới? Hãy cân nhắc đăng kí gói cao hơn. Khám phá các gói của chúng tôi và chọn gói phù hợp nhất với nhu cầu của công ty bạn." + "components.locked_features.locked_workspace_popup.text": "Whoops!!Bạn muốn tạo thêm không gian làm việc mới? Hãy cân nhắc đăng kí gói cao hơn. Khám phá các gói của chúng tôi và chọn gói phù hợp nhất với nhu cầu của công ty bạn.", + "scenes.app.popup.adduser.magiclinks.genrator_info": "Liên kết lời mời đến không gian làm việc", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "Liên kết mới được tạo", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "Đã sao chép thành công vào bộ nhớ tạm", + "scenes.app.popup.adduser.magiclinks.action_copy": "Sao chép", + "scenes.app.popup.adduser.magiclinks.action_generate": "Tạo ra", + "scenes.apps.board.new_task": "+ Công việc mới", + "components.alert.confirm_click": "Xác nhận hành động của bạn bằng cách nhấp vào OK.", + "components.searchpopup.tasks": "Công việc", + "scenes.app.mainview.advanced_search_placeholder": "Tìm kiếm nâng cao", + "components.searchpopup.hide_filters": "ẩn bộ lọc", + "components.searchpopup.show_filters": "hiện bộ lọc", + "components.searchpopup.load_more": "Tải thêm kết quả", + "general.more": "Thêm", + "scenes.apps.board.archived_tasks": "Công việc đã lưu trữ ({{$ 1}})", + "scenes.apps.board.active_tasks": "Công việc đang thực hiện", + "scenes.apps.board.kanban": "Kanban", + "scenes.apps.board.display_as": "Hiển thị dưới dạng", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "Phiên bản", + "components.reminder.hours_bef": "giờ trước", + "components.reminder.days_bef": "ngày hôm trước", + "components.reminder.weeks_bef": "vài tuần trước", + "components.reminder.by_email": "E-mail", + "scenes.apps.calendar.reminders": "(các) lời nhắc nhở", + "scenes.apps.calendar.video_link": "Nhấp để mở liên kết", + "scenes.app.mainview.discussion": "Thảo luận", + "components.tagpicker.notag": "Không có thẻ", + "scenes.apps.tasks.modals.attachments": "Tập tin đính kèm", + "components.calendar.calendarselector.from": "Từ", + "components.attachmentpicker.from_computer": "Từ thiết bị của bạn", + "components.attachmentpicker.from_twake": "Từ tài liệu Twake", + "components.attachmentpicker.file": "Tập tin", + "components.attachmentpicker.remove_attach": "Xóa tệp đính kèm", + "components.drive.elements.see": "Nhìn thấy", + "components.drive.elements.current_name": "Tên thật: ", + "scenes.app.integrations_parameters.company_application_popup.btn": "Cài đặt", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "Thông tin", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "Trang mạng", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "Ngày thành lập", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "Chỉ", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "Xóa khỏi công ty", + "scenes.app.integrations_parameters.company_applications_table.title": "Đã cài đặt trong công ty của bạn", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "Đã xóa thành công {{$1}} khỏi công ty của bạn", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "Đã thêm thành công {{$1}} vào công ty của bạn", + "components.reminder.notification": "Thông báo", + "scenes.join.loading": "Đang tải…", + "scenes.join.wrong_link_title": "Liên kết này không còn nữa", + "scenes.join.wrong_link_description": "Yêu cầu người đã mời bạn tham gia công ty này để có liên kết mới hoặc tạo công ty của riêng bạn", + "scenes.join.create_the_company_button": "Tạo công ty", + "scenes.join.join_workspace_from_company": "Tham gia {{$1}} từ {{$2}}!", + "scenes.join.twake_description": "Twake là một không gian làm việc kỹ thuật số mã nguồn mở được xây dựng để cải thiện năng suất nhóm của bạn", + "scenes.join.login_first_button": "Đăng nhập hoặc tạo tài khoản trước", + "scenes.join.join_the_team_button": "Tham gia nhóm", + "scenes.apps.drive.move_text2": "Di chuyển", + "scenes.apps.drive.remove_attachs": "Xóa tệp đính kèm", + "scenes.app.popup.createcompany.try_again": "Vui lòng thử lại.", + "scenes.apps.drive.right_preview.public": "Quyền truy cập công khai", + "components.drive.elements.configurate_mod": "Định cấu hình mod ...", + "components.drive.elements.manage_version": "Quản lý các phiên bản", + "scenes.app.popup.workspace.edit_temp": "Chỉnh sửa tài khoản tạm thời", + "scenes.app.popup.workspace.create_temp": "Tạo tài khoản tạm thời", + "scenes.apps.tasks.active_tasks": "nhiệm vụ tích cực", + "scenes.apps.drive.right_preview.versions": "Phiên bản", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "Quản lý các ứng dụng và trình kết nối của bạn.", + "scenes.app.popup.appsparameters.pages.icon": "Biểu tượng", + "scenes.app.integrations_parameters.title": "Tích hợp", + "scenes.app.integrations_parameters.applications_table.title": "Các tích hợp khác", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "Ứng dụng tìm kiếm", + "scenes.app.integrations_parameters.company_application_popup.tag": "Cài đặt", + "scenes.apps.board.all_boards": "Tất cả các bảng", + "components.userlistmanager.no_users": "Không có người dùng.", + "scenes.apps.drive.used": "được sử dụng trong thư mục này", + "components.reminder.minutes_bef": "phút trước", + "login.create_account": "Tạo tài khoản", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "Không gian làm việc mặc định", + "\"": "\"", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "Chưa có ai mời bạn vào không gian làm việc.", + "scenes.apps.messages.message.types.no_message_in_thread": "Chưa có ai trả lời.", + "'": "'", + "login.login_error": "Lỗi khi đăng nhập", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "Tự động mời tất cả người dùng không gian làm việc vào kênh này", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "Bạn sắp xóa {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "Bạn vẫn còn thành viên {{$1}} trong {{$2}}. Bạn nên xóa tất cả các thành viên để có thể xóa không gian làm việc này.", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "Tôi hiểu rằng tất cả các tin nhắn và tệp trong không gian làm việc của tôi sẽ bị xóa.", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "Kích thước biều tượng tối đa là 5mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "Định dạng sai, chỉ cho phép png gif và jpg", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "Lỗi không rõ", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "Lỗi", + "scenes.app.channelsbar.currentuser.reset": "Cài lại", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "Viết ít nhất ba chữ cái để hiển thị người dùng", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "Không tìm thấy người dùng", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "Không tìm thấy biểu tượng cảm xúc", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "Không tìm thấy lệnh", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} đang viết ...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} và {{$2}} đang viết ...", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}, {{$2}} và {{$3}} người dùng khác đang viết ...", + "components.locked_features_components.locked_invite_alert.message_part_1": "Công ty của bạn đã đạt đến giới hạn tối đa là {{$1}} thành viên. Xin vui lòng ", + "components.locked_features_components.locked_invite_alert.message_link": "nâng cấp công ty của bạn", + "components.locked_features_components.locked_invite_alert.message_part_2": " để mời thêm thành viên.", + "components.locked_features_components.locked_invite_alert.message_magic_link": " liên hệ với chủ sở hữu hoặc quản trị viên của công ty bạn.", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "Xem tất cả các thành viên công ty của tôi trên bảng điều khiển", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "Mô tả ứng dụng của bạn bằng một vài từ", + "scenes.app.popup.appsparameters.pages.application_creator.title": "Tích hợp mới", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "Nếu bạn không biết làm thế nào để điền vào những điều này, hãy truy cập ", + "scenes.app.popup.appsparameters.pages.app.private_key": "Khóa cá nhân", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "Đã xóa ứng dụng {{$1}} thành công!", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "Lỗi khi xóa ứng dụng {{$1}}!", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "Ứng dụng {{$1}} thành công!", + "scenes.app.integrations_parameters.add_application": "Tích hợp mới", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "Cài đặt nhà phát triển", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "Tôi hiểu rằng chủ sở hữu và quản trị viên của công ty này sẽ có thể sửa đổi và xuất bản ứng dụng này.", + "twake.application.access.title": "Chọn phạm vi phù hợp cho ứng dụng của bạn.", + "twake.application.access.no_default_scopes_available'": "Tích hợp này không có bất kỳ quyền truy cập {{$1}} nào", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "tài liệu API Twake", + "components.rich_text_editor.plugins.suggestions.loading": "Tìm kiếm thêm", + "components.open_desktop_popup.subtitle": "được mở trong ứng dụng Twake", + "components.open_desktop_popup.open_here_link": "Thay vào đó hãy mở ở đây", + "molecules.download_banner.title": "Tận dụng tối đa twake, tải xuống ứng dụng dành cho máy tính để bàn ngay bây giờ", + "molecules.download_banner.download_button": "Tải xuống ứng dụng dành cho máy tính để bàn", + "scenes.app.channelsbar.channel_copy_link": "Sao chép liên kết kênh", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "Cập nhật thành công", + "components.searchpopup.no_results_for": "Không có kết quả cho", + "components.searchpopup.try_new_search": "Thử một tìm kiếm mới", + "components.searchpopup.all": "Tất cả các", + "components.searchpopup.chats": "Trò chuyện", + "components.searchpopup.media": "Phương tiện truyền thông", + "components.searchpopup.files": "Các tập tin", + "components.searchpopup.recent_chats": "Các cuộc trò chuyện gần đây", + "components.searchpopup.recent_media": "Phương tiện truyền thông gần đây", + "components.searchpopup.recent_files": "Tệp gần đây", + "components.searchpopup.recent_channels_and_contacts": "Các kênh và địa chỉ liên hệ gần đây", + "components.searchpopup.header_title": "Tìm kiếm", + "components.searchpopup.scope.company": "trong tất cả các công ty", + "components.searchpopup.messages": "Tin nhắn", + "components.searchpopup.scope.channel": "trong kênh này", + "components.searchpopup.channels": "Kênh truyền hình" } diff --git a/twake/frontend/public/locales/zh_Hans.json b/twake/frontend/public/locales/zh_Hans.json index 3ffe5844ce..4b1cbd374e 100644 --- a/twake/frontend/public/locales/zh_Hans.json +++ b/twake/frontend/public/locales/zh_Hans.json @@ -64,5 +64,847 @@ "scenes.app.header.alt_notifications": "通知", "general.retry": "重试", "general.cancel": "取消", - "general.continue": "继续" -} \ No newline at end of file + "general.continue": "继续", + "scenes.app.popup.adduser.magiclinks.genrator_info": "工作区邀请链接", + "scenes.app.popup.adduser.magiclinks.new_link_generated": "新链接已生成", + "scenes.app.popup.adduser.magiclinks.copied_to_clipboard": "已成功复制到剪贴板", + "scenes.app.popup.adduser.magiclinks.action_copy": "复制", + "scenes.app.popup.adduser.magiclinks.action_generate": "产生", + "scenes.app.popup.appsparameters.pages.available_publication_alert": "您的应用程序的发布目前正在等待 Twake 团队的验证。", + "scenes.app.popup.appsparameters.pages.button_force": "整个公司的力量", + "scenes.app.popup.appsparameters.pages.read_privileges_label": "读取权限", + "scenes.app.popup.appsparameters.pages.remove_app": "永久删除应用程序 {{$1}}。", + "scenes.app.popup.appsparameters.pages.remove_app_from_company": "从整个公司中删除", + "scenes.app.popup.appsparameters.pages.remove_app_from_workspace": "从工作区中删除", + "scenes.app.popup.appsparameters.pages.string_information": "此字符串标识您的应用程序并将用于消息命令。", + "scenes.app.popup.appsparameters.pages.title_tester": "Twakecode 测试员", + "scenes.app.popup.appsparameters.pages.url_reception_events_label": "活动接收网址", + "scenes.app.popup.appsparameters.pages.waiting_availability_application": "等待...", + "scenes.app.popup.appsparameters.pages.write_privileges_label": "写入权限", + "scenes.app.popup.appsparameters.pages.update_button": "更新", + "scenes.app.popup.createworkspacepage.add_subtitle": "需要更多的空间?", + "scenes.app.popup.createworkspacepage.create_new_workspace": "创建新工作区", + "scenes.app.popup.createworkspacepage.placeholder_name": "工作区名称", + "scenes.app.popup.userparameter.pages.frequency_notif_configuration_description": "设置手机通知的频率。", + "scenes.app.popup.userparameter.pages.frequency_notif_subtitle": "通知频率", + "scenes.app.popup.workspaceparameter.pages.access_apps": "访问您的应用程序和连接器", + "scenes.app.popup.workspaceparameter.pages.moderator_status": "工作区版主", + "scenes.app.popup.workspaceparameter.pages.alert_impossible_removing": "您不能离开工作区,因为您是最后一位管理员。您可以定义新管理员或删除/归档此工作区。", + "scenes.app.popup.workspaceparameter.pages.all_apps_small_text": "所有应用", + "scenes.app.popup.workspaceparameter.payments_subscriptions_title": "付款和订阅", + "scenes.apps.calendar.my_calendar": "我的日历", + "scenes.apps.calendar.my_calendar_label": "我的日历", + "scenes.apps.calendar.my_calendar_menu": "我的日历", + "scenes.apps.calendar.today_menu": "今天", + "scenes.apps.calendar.week_option": "星期", + "scenes.apps.calendar.workspace": "工作区", + "scenes.apps.calendar.workspace_label": "这个工作区", + "scenes.apps.calendar.workspace_menu": "工作区", + "scenes.apps.drive.add_button": "添加", + "services.apps.messages.no_command_possible": "我们无法执行命令“{{$1}}”,因为“{{$2}}”不存在或不允许创建命令。", + "services.user.notification_parameters_update_alert": "通知设置已更新。", + "services.user.update_password_alert": "您的密码已更新。", + "scenes.apps.tasks.board.tasks.use_deadline": "使用期限", + "scenes.apps.tasks.board.tasks.use_starttime": "使用开始时间", + "scenes.apps.tasks.board.tasks.in_list": "在列表中", + "scenes.apps.tasks.board.starts": "启动", + "scenes.apps.tasks.board.ends": "为", + "scenes.apps.tasks.board.list_name": "列表名称", + "scenes.app.popup.sync_calendar": "同步您的日历。", + "scenes.apps.parameters.workspace_sections.workspace.logo_company": "公司标志", + "scenes.app.popup.workspaceparameter.pages.logo_company_modify_description": "编辑公司形象 ", + "components.listmanager.filter": "筛选", + "scenes.apps.tasks.no_connector": "无接头", + "components.attachmentpicker.add_attachment": "添加附件", + "components.input.copied": "已复制", + "components.drive.new_versions": "添加新版本", + "components.drive.navigators.directory_not_found": "未找到目录。", + "components.drive.right_preview.suppress_link": "取消链接", + "components.drive.right_preview.create_link": "创建访问链接", + "components.drive.moove_here": "搬来这", + "components.verify_mail.paragraph": "如果您愿意,您可以稍后再做,但未经验证的帐户只能访问有限版本的 Twake", + "services.console_services.toaster.add_email_error_message": "添加 {{$1}} 时出错", + "scenes.client.channels_bar.modals.guest_management.input_placeholder": "搜索来宾或待处理的电子邮件", + "scenes.client.channels_bar.modals.guest_management.tips": "使用上面的输入开始添加或搜索电子邮件", + "components.on_boarding.company_billing_banner.admin_or_owner_text": "您的公司订阅存在问题。请看看你的", + "components.on_boarding.company_billing_banner.guest_or_member_text": "您的公司订阅存在问题。请联系公司老板或管理员!", + "components.on_boarding.company_billing_banner.link": "公司认购计划", + "components.on_boarding.popups.blocked_company.description": "您对 Twake 的订阅已过期。请联系贵公司的老板或管理员进行更新,以便再次与您的团队沟通!", + "components.on_boarding.popups.blocked_company.learn_more_text": "想了解更多公司订阅计划?", + "components.upload.drop_files.toaster.error": "您不能上传超过 {{$1}} 个文件", + "components.emoji_picker.categories.frequently_used": "经常使用", + "components.emoji_picker.categories.activity": "活动", + "components.emoji_picker.categories.travel_and_places": "旅行和地方", + "components.emoji_picker.categories.objects": "对象", + "components.emoji_picker.categories.symbols": "符号", + "components.emoji_picker.categories.flags": "旗帜", + "components.emoji_picker.categories.search_result": "搜索结果", + "scenes.app.integrations_parameters.title": "集成", + "scenes.app.integrations_parameters.applications_table.name": "姓名", + "scenes.app.integrations_parameters.applications_table.title": "其他集成", + "scenes.app.integrations_parameters.company_application_popup.btn": "安装", + "scenes.app.integrations_parameters.company_application_popup.tab_btn_info": "资讯", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.created_item": "创立日期", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.version_item": "版本", + "scenes.app.integrations_parameters.company_applications_table.more_menu.remove_application": "从公司除名", + "scenes.app.integrations_parameters.company_applications_table.name": "姓名", + "scenes.app.integrations_parameters.company_applications_table.title": "安装在贵公司", + "scenes.join.loading": "正在加载…", + "scenes.join.wrong_link_title": "此链接不再可用", + "scenes.join.wrong_link_description": "向邀请您加入该公司的人询问新链接或创建您自己的公司", + "scenes.join.create_the_company_button": "创建公司", + "scenes.join.join_workspace_from_company": "从{{$2}}加入{{$1}}!", + "scenes.join.twake_description": "Twake 是一个开源数字工作区,旨在提高您的团队生产力", + "scenes.join.login_first_button": "首先登录或创建一个帐户", + "scenes.join.join_the_team_button": "加入团队", + "general.unarchive": "取消存档", + "application.load.longer": "服务器响应时间比预期长,请稍候或重新加载页面...", + "scenes.app.side_app.messages_thread_title": "{{$1}} • 消息线程", + "scenes.app.workspaces.create_company.group_data": "配置您的新组", + "scenes.app.workspaces.create_company.group_data.group_main_activity.food": "食物", + "scenes.app.workspaces.create_company.group_data.group_main_activity.administration": "行政", + "scenes.apps.calendar.event_edition.checkbox_all_day": "一整天", + "scenes.apps.calendar.event_edition.title_confidentiality": "保密", + "scenes.apps.calendar.event_view.article_until": "到", + "scenes.apps.calendar.calendar_modal.participants": "参与者", + "scenes.apps.calendar.calendar_modal.placeholder": "姓名", + "scenes.apps.calendar.left.calendars": "日历", + "scenes.apps.drive.navigators.navigator_content.directory_name": "目录名", + "scenes.apps.drive.navigators.navigator_content.files": "文件", + "scenes.apps.drive.navigators.navigator_labels.title": "标签", + "scenes.apps.drive.navigators.new_file.untitled": "无标题", + "scenes.apps.drive.navigators.new_file.create_file.type": "类型", + "scenes.apps.drive.navigators.new_file": "新文件", + "scenes.apps.drive.preview_bloc.operations_download": "下载", + "scenes.apps.drive.preview_bloc.error_file": "文件未找到", + "scenes.apps.drive.right_preview.operations_restore": "恢复", + "scenes.apps.drive.right_preview.operations_delete": "移到废纸篓", + "scenes.apps.drive.right_preview.public_link": "公共链接", + "scenes.apps.messages.messages": "留言", + "scenes.apps.messages.chatbox.chat.delete_message": "删除此消息", + "scenes.apps.messages.chatbox.chat.delete_message_btn": "删除留言", + "scenes.apps.messages.left_bar.stream_modal.placeholder_name": "姓名", + "scenes.apps.messages.left_bar.stream.add_to_favorites": "添加到收藏夹", + "scenes.apps.messages.left_bar.stream.remove_from_favorites": "从收藏夹中删除", + "scenes.apps.messages.left_bar.stream.notifications": "通知...", + "scenes.apps.messages.left_bar.stream.notifications.all": "任何消息", + "scenes.apps.messages.left_bar.stream.notifications.mentions": "{{$1}}、{{$2}} 和 {{$3}}", + "scenes.apps.messages.left_bar.stream.notifications.me": "{{$1}} 仅", + "scenes.apps.messages.left_bar.stream.notifications.never": "没有", + "scenes.apps.parameters.workspace_sections.workspace": "工作区", + "scenes.apps.parameters.workspace_sections.members": "参与者", + "scenes.apps.parameters.group_sections.workspaces": "工作区", + "scenes.apps.parameters.group_sections.apps": "应用", + "scenes.apps.account.title": "账户参数", + "scenes.apps.account.account.menu_title": "帐户", + "scenes.apps.account.languages.menu_title": "语", + "scenes.apps.account.account.firstname": "名", + "scenes.apps.account.account.lastname": "姓", + "scenes.apps.account.account.username": "用户名", + "scenes.apps.account.account.change_username": "更改您的唯一用户名。", + "scenes.apps.account.account.emails": "电子邮件", + "scenes.apps.account.account.main_email": "主要邮箱", + "scenes.apps.account.account.email_add": "添加新电子邮件", + "scenes.apps.account.account.email_add_modal.invalid_code": "此代码无效", + "scenes.apps.account.account.password": "密码", + "scenes.apps.account.account.password_modal.old_password": "当前密码", + "scenes.apps.account.account.password_modal.password": "新密码", + "scenes.apps.account.account.password_modal.bad_old_password": "旧密码不正确。", + "scenes.apps.account.account.password_modal.bad_password": "您的密码不匹配或密码太短。请输入至少 8 个字符的密码。", + "scenes.apps.account.account.logout": "登出", + "scenes.apps.account.languages.text": "更改 Twake 语言。", + "scenes.apps.account.notifications.title": "通知", + "scenes.apps.account.notifications.keywords_subtitle": "关键词", + "scenes.apps.account.notifications.keywords_placeholder": "开发,wifi,代码,...", + "scenes.apps.account.notifications.disturb_option_a": "之间不要向我发送推送通知 ", + "scenes.apps.account.notifications.disturb_option_b": " 和 ", + "scenes.apps.account.notifications.disturb_option_c": " (当地时区)", + "scenes.apps.account.notifications.devices_subtitle": "设备通知", + "scenes.apps.account.notifications.devices_option_ever": "始终向我发送推送通知", + "scenes.apps.account.notifications.devices_option_inactive": "当我在桌面上处于非活动状态时向我发送推送通知", + "scenes.apps.account.notifications.devices_option_never": "从不向我发送推送通知", + "scenes.apps.account.notifications.privacy_subtitle": "隐私", + "scenes.apps.account.notifications.mail_subtitle": "电子邮件通知", + "scenes.apps.account.notifications.sound": "声音通知", + "scenes.apps.parameters.workspace_sections.members.invite_btn": "添加用户", + "scenes.apps.tasks.boards": "板", + "scenes.apps.tasks.connectors_menu": "连接器...", + "scenes.apps.tasks.connectors_search_menu": "搜索连接器...", + "scenes.apps.tasks.no_connectors_menu_text": "您没有任何可以连接到日历的连接器。", + "scenes.apps.tasks.unconfigured_tab": "此选项卡尚未配置。", + "scenes.apps.tasks.choose_board_button": "选择一块板", + "scenes.apps.tasks.new_board.title": "新板", + "scenes.apps.tasks.new_board.edit_title": "编辑板", + "scenes.apps.tasks.task": "任务", + "scenes.apps.tasks.no_tasks": "没有任务", + "scenes.apps.tasks.task_status.todo": "去做", + "scenes.apps.tasks.task_status.current": "当前的", + "scenes.apps.tasks.task_status.done": "完毕", + "scenes.apps.tasks.task.description": "描述", + "scenes.apps.tasks.task.assignees": "受让人", + "scenes.apps.tasks.task.edit.dates": "日期", + "scenes.apps.tasks.list_modal.remove_archived_tasks": "删除归档任务 ({{$1}})", + "scenes.login.footer.go_to_twake": "去 twakeapp.com", + "scenes.login.footer.branding": "您在 {{$1}} ({{$2}}) 私人 Twake 服务器上。 ", + "scenes.login.create_account.title": "创建一个新账户", + "scenes.login.create_account.email": "电子邮件", + "scenes.login.create_account.email_used": "此电子邮件已被使用。", + "scenes.login.create_account.username": "用户名", + "scenes.login.create_account.username_already_exist": "此用户名已被使用", + "scenes.login.create_account.fill_in_username": "您必须填写您的用户名", + "scenes.login.create_account.fill_in_email": "您必须使用正确的电子邮件填写您的电子邮件", + "scenes.login.create_account.too_short_password": "您的密码必须至少包含 8 个字符。", + "scenes.login.create_account.firstname": "名", + "scenes.login.create_account.newsletter": "接收有关 Twake 的信息", + "scenes.login.create_account.lastname": "姓", + "scenes.login.forgot_password.title": "忘记密码?", + "scenes.login.forgot_password.text": "您将通过电子邮件收到一个 9 位代码以验证您的身份。", + "scenes.login.forgot_password.text2": "您将收到一个 9 位数的代码。请在下面的字段中输入它以继续。", + "scenes.login.forgot_password.invalid_code": "此代码无效。", + "scenes.login.forgot_password.text3": "为您的帐户输入新密码。", + "scenes.login.forgot_password.password": "密码", + "scenes.login.forgot_password.password2": "确认密码", + "scenes.login.forgot_password.password_dont_match": "您的密码不匹配或密码太短。请输入至少 8 个字符的密码。", + "scenes.login.home.title": "登录 Twake", + "scenes.login.home.subtitle": "高兴看到你", + "scenes.login.home.email": "电子邮件", + "scenes.login.home.unable_to_connect": "无效证件", + "scenes.login.home.password": "密码", + "scenes.login.home.login_btn": "登录", + "general.open": "打开", + "components.calendar.repetition.years": "年)", + "components.calendar.repetition.custom_recurrence": "自定义重复", + "components.calendar.repetition.occurrence": "发生次数", + "components.calendar.repetition.repeat_on": "重复", + "scenes.app.channelsbar.currentuser.add_apps": "搜索应用", + "scenes.app.channelsbar.currentuser.change_my_status": "更改我的状态", + "scenes.app.channelsbar.currentuser.collaborateurs": "用户", + "scenes.app.channelsbar.currentuser.create_workspace_page": "创建工作区", + "scenes.app.channelsbar.currentuser.invited_status": "你是客人。", + "scenes.app.channelsbar.currentuser.title": "帐号设定", + "scenes.app.channelsbar.currentuser.workspace_info": "您位于 {{$2}} 组的工作区 {{$1}}", + "scenes.app.channelsbar.currentuser.workspace_parameters": "工作区设置", + "scenes.app.channelsbar.currentuser.logout": "登出", + "scenes.app.channelsbar.currentuser.update": "更新", + "scenes.app.channelsbar.currentuser.disable_notifications": "禁用", + "scenes.app.channelsbar.currentuser.disabling_notifications": "禁用 1 小时", + "scenes.app.channelsbar.currentuser.disabling_notifications_until": "禁用至上午 9 点明天", + "scenes.app.channelsbar.currentuser.reactivate_notifications": "重新激活", + "scenes.app.channelsbar.modify_channel_menu": "编辑频道", + "scenes.app.channelsbar.guest_management": "宾客管理", + "scenes.app.channelsbar.read_sign": "标记为已读", + "scenes.app.channelsbar.unread_sign": "标记为未读", + "scenes.app.channelsbar.channel_leaving": "离开频道", + "scenes.app.channelsbar.channel_removing": "删除频道", + "scenes.app.channelsbar.company_invitation_alert_subtitle": "您可以通过单击此框架将这些渠道导入您的业务以保持井井有条。", + "scenes.app.channelsbar.company_invitation_alert_title": "公司邀请您 ", + "scenes.app.popup.appsparameters.pages.alert_published_app": "您的应用程序已发布,您无法对其进行编辑。", + "scenes.app.popup.appsparameters.pages.allowed_ip_adresses_method": "在开发中使用 * 以允许所有 IP 地址。", + "scenes.app.popup.appsparameters.pages.error_check_needed": "发生了错误;检查您的信息。", + "scenes.app.popup.appsparameters.pages.error_message": "此名称已被另一个应用程序使用;请选择另一个。", + "scenes.app.popup.appsparameters.pages.event_subtitle": "活动", + "scenes.app.popup.workspaceparameter.pages.back_to_search_button": "返回搜索", + "scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button": "邀请用户", + "scenes.app.popup.workspaceparameter.pages.collaborateurs": "用户", + "scenes.app.popup.workspaceparameter.pages.company_developped_apps_subtitle": "公司开发的应用", + "scenes.app.popup.workspaceparameter.pages.company_identity_title": "公司身份", + "scenes.app.popup.workspaceparameter.pages.company_name_description": "更改这家公司的名称", + "scenes.app.popup.workspaceparameter.pages.company_name_label": "公司名称", + "scenes.app.popup.workspaceparameter.pages.configuration_notif": "配置", + "scenes.app.popup.workspaceparameter.pages.no_app_information": "您在此工作区中没有应用程序", + "scenes.app.popup.workspaceparameter.pages.quit_workspace_menu": "离开这个工作区", + "scenes.app.popup.workspaceparameter.pages.remove_from_company_text": "从整个公司中删除", + "scenes.app.popup.workspaceparameter.pages.research_by": "按名称和类别搜索应用程序", + "scenes.app.popup.workspaceparameter.pages.researching_apps_button": "搜索应用程序...", + "scenes.app.popup.workspaceparameter.pages.show_button": "展示", + "scenes.apps.calendar.modals.remove_button": "删除", + "scenes.apps.calendar.modals.remove_event_button": "删除事件", + "scenes.apps.calendar.modals.remove_event_text": "删除活动?", + "scenes.apps.calendar.modals.title_placeholder": "标题", + "scenes.apps.calendar.modify_calendar_menu": "编辑日历", + "scenes.apps.calendar.month_option": "月", + "scenes.apps.drive.viewer.open_with_button": "打开用...", + "scenes.apps.messages.input.placeholder": "写一个信息。使用@ 引用用户。", + "scenes.apps.messages.input.edited": "已编辑", + "scenes.apps.messages.just_you": "仅对您可见", + "scenes.apps.messages.message.new_messages_bar": "新消息", + "scenes.apps.messages.message.cancel_button": "取消", + "scenes.login.verifymail.signin_button": "登录", + "scenes.login.verifymail.success": "您的邮箱已成功验证!", + "scenes.login.verifymail.verification_waiting": "等待验证...", + "scenes.no_panic": "不要惊慌!只需重新加载此页面即可修复 Twake。", + "services.apps.calendar.deadline_icon": "最后期限", + "services.apps.calendar.event_icon": "事件", + "services.apps.calendar.move_icon": "移动", + "services.apps.calendar.reminder_icon": "提醒", + "services.apps.messages.no_app": "此应用程序不存在。", + "scenes.apps.calendar.unconfigured_tab": "此选项卡尚未配置。", + "scenes.apps.drive.top_menu_more": "更多的", + "scenes.apps.drive.top_menu_no_items": "{{$1}} 项", + "scenes.apps.messages.new_thread": "开始新的讨论", + "scenes.apps.messages.input.send_message": "发信息", + "scenes.apps.messages.input.emoji": "表情符号", + "scenes.apps.messages.input.hide_formatting": "隐藏格式", + "scenes.apps.messages.input.show_formatting": "显示格式", + "scenes.apps.tasks.my_tasks": "我的任务", + "scenes.apps.tasks.board.place_holder": "板名", + "scenes.apps.tasks.board.tasks.subtask": "子任务", + "scenes.apps.tasks.board.tasks.add_subtask": "添加子任务", + "components.tagpicker.tag_name": "标签名称", + "components.upload.drop_files": "将您的文件放在这里", + "components.workspace.list_manager.no_workspace": "没有工作区", + "components.attachmentpicker.from_computer": "从您的设备", + "components.attachmentpicker.from_twake": "从调整文件", + "components.attachmentpicker.file": "文件", + "components.attachmentpicker.remove_attach": "删除附件", + "scenes.apps.drive.remove_attachs": "删除附件", + "components.drive.elements.see": "看", + "components.drive.elements.current_name": "现名: ", + "scenes.apps.drive.right_preview.public": "公共访问", + "components.drive.elements.configurate_mod": "配置模块...", + "components.drive.elements.manage_version": "管理版本", + "scenes.app.popup.createcompany.try_again": "请再试一次。", + "components.notifications.hidden_notifications_button.children": "新消息", + "scenes.client.mainview.tabs.tabstemplateeditor.select_placeholder": "应用", + "scenes.client.channelbar.channelmemberslist.no_members": "此频道中没有用户,您可以通过单击添加用户来邀请他们。", + "scenes.app.channelsbar.hide_discussion_leaving.menu": "隐藏讨论", + "scenes.app.popup.adduserfromtwakeconsole.current_users_state": "{{$1}} 电子邮件将被添加", + "components.newversion.new_version_component.row.part_1": "您运行的是过时的 Twake 版本", + "general.re_send": "重发", + "components.account_verication_status_blocked": "锁定", + "components.unverified_account.re_send_email": "没有收到邮件?", + "components.blocked_account.trial_period_over": "您的试用期已过。要解锁您的帐户并访问所有功能,请通过电子邮件确认验证您的帐户", + "scenes.app.popup.workspaceparameter.pages.workspace_partner_tabs.members.table.tags": "角色", + "general.email": "电子邮件", + "components.locked_features.locked_workspace_popup.title": "您无法创建更多工作区", + "scenes.login.create_account.step_3_mail_sent": "我们已通过电子邮件向您发送激活链接。", + "scenes.login.create_account.step_3_subtitle": "最后一步——我们需要验证你不是机器人!", + "scenes.app.workspaces.create_company.company_name.placeholder": "公司名", + "scenes.app.workspaces.create_company.company_name.title_1": "开始,", + "scenes.app.workspaces.create_company.company_name.title_2": "注明贵公司的名称。", + "scenes.app.workspaces.create_company.default_workspace_name": "主要的", + "scenes.app.workspaces.create_company.importations.title_1": "已经在使用数字工具?立即导入或集成您的工具!", + "scenes.app.workspaces.create_company.importations.title_2": "不用担心,您可以稍后再做!", + "scenes.app.workspaces.create_company.invitations.title_2": "将用户添加到您的团队。", + "scenes.app.workspaces.create_company.title": "创建我的公司", + "scenes.app.workspaces.welcome_page.add_secondary_emails": "添加辅助电子邮件", + "scenes.app.workspaces.welcome_page.added_to_company": "您已受邀参加 ", + "scenes.app.workspaces.welcome_page.create_my_company": "创建我的公司", + "scenes.app.workspaces.welcome_page.lets_go": "我们走吧!", + "scenes.app.workspaces.welcome_page.may_be_invited_with_secondary_emails": "您是使用其他电子邮件地址被邀请的吗?", + "scenes.app.workspaces.welcome_page.no_company_subtitle": "哦,好吧……看起来还没有人邀请你到工作区。", + "scenes.app.workspaces.welcome_page.ready_to_work": "您现在可以开始工作了。", + "scenes.app.workspaces.welcome_page.see_you_soon": "再见!", + "scenes.app.workspaces.welcome_page.try_again": "再试一次", + "scenes.app.workspaces.welcome_page.twake_team": "调整", + "scenes.app.workspaces.welcome_page.welcome_header": "欢迎来到特瓦克!", + "scenes.app.workspaces.welcome_page.add_secondary_emails_comment": "您可以将多个电子邮件地址链接到您的帐户;只有一个地址将用于向您发送通知。", + "scenes.app.workspaces.welcome_page.main_mail_title": "主要地址", + "scenes.app.workspaces.welcome_page.other_mail_title": "辅助地址", + "scenes.app.workspaces.welcome_page.add_new_email": "添加电子邮件", + "scenes.app.workspaces.welcome_page.code_verification": "验证码", + "scenes.app.workspaces.welcome_page.new_email": "添加辅助电子邮件", + "scenes.app.workspaces.welcome_page.we_sent_you_mail": "我们通过 {{$1}} 向您发送了验证码", + "scenes.app.workspaces.welcome_page.done": "我受够了", + "scenes.login.forgot_password.finished": "您的密码已成功更新。", + "scenes.apps.account.account.description_main": "您的主要地址是 Twake 发送通知的地方。您的辅助地址允许您自动被邀请到使用它们的工作区。", + "scenes.apps.account.account.emails.description": "管理您的不同电子邮件地址。", + "scenes.apps.account.account.make_main": "设置主要", + "scenes.apps.account.account.password.description": "更改您的密码。", + "scenes.apps.account.identity": "身份", + "scenes.apps.account.identity.description": "更改其他 Twake 用户可见的名字、姓氏和个人资料图片。", + "scenes.apps.account.preference": "喜好", + "scenes.apps.account.thumbnail.max_weight": "最大大小 5 MB", + "scenes.apps.account.account.email_add_modal.confirm": "确认此电子邮件", + "app.name.twake_calendar": "日历", + "general.verify": "核实", + "scenes.app.workspaces.create_company.group_data.title": "我们很快——我们只需要一些统计信息。", + "scenes.app.channelsbar.currentuser.company_messages_counter_header": "留言号码", + "scenes.app.channelsbar.currentuser.company_messages_counter_info": "在 Twake 的免费版本上,您只能访问 {{$1}} 更新的消息。", + "scenes.app.channelsbar.currentuser.company_messages_counter_link": "显示更多计划", + "scenes.app.channelsbar.channelsuser.new_private_discussion": "新的私人讨论", + "scenes.app.channelsbar.channelsuser.no_private_message_invite_collaboraters": "没有私信。邀请用户!", + "scenes.app.channelsbar.channelsuser.private_messages": "直接消息", + "scenes.app.channelsbar.channelsworkspace.channel_title": "频道", + "scenes.app.channelsbar.channelsworkspace.channel_title.favorite": "收藏夹", + "scenes.app.channelsbar.channelsworkspace.create_channel": "创建频道", + "scenes.app.channelsbar.channelsworkspace.no_channel": "您还没有加入任何频道", + "scenes.app.channelsbar.initial_instructions_tutorial": "选择名字、姓名和个人资料图片。", + "scenes.app.channelsbar.installation_desktop_tutorial": "安装桌面应用程序", + "scenes.app.channelsbar.invitation_collaboraors_tutorial": "邀请用户进入您的工作区。", + "scenes.app.channelsbar.public_channel_label": "民众", + "scenes.app.channelsbar.private_channel_label": "私人的", + "scenes.app.channelsbar.sending_message_instruction": "在讨论中发送您的第一条消息", + "scenes.app.channelsbar.tutorial_alert": "不再显示此框架?", + "scenes.app.channelsbar.welcome": "欢迎来到 Twake", + "scenes.app.channelsbar.welcoming_message_subtitle": "只需点击几下即可成为 Twake 专家!", + "scenes.app.mainview.instruction_current_tab": "首先选择左侧的频道。", + "scenes.app.mainview.tabs.no_connected_connectors_for_channel": "您没有可以连接到通道的连接器。", + "scenes.app.mainview.tabs.rename": "改名", + "scenes.app.mainview.tabs.searching_connectors": "搜索连接器...", + "scenes.app.popup.adduser.adresses_message": "请用逗号或空格分隔地址。请记住,Twake 可以根据您的订阅限制邀请数量。", + "scenes.app.popup.appsparameters.pages.amazing_app_name": "我惊人的应用程序", + "scenes.app.popup.appsparameters.pages.api_data_description": "Twake API 的有用数据。", + "scenes.app.popup.appsparameters.pages.api_parameters_label": "接口设置", + "scenes.app.popup.appsparameters.pages.app_name_label": "应用名称", + "scenes.app.popup.appsparameters.pages.app_modification_right": "该公司的所有经理都可以编辑此应用程序。", + "scenes.app.popup.appsparameters.pages.app_privileges_information": "定义您的应用程序可以编辑和读取的内容。", + "scenes.app.popup.appsparameters.pages.app_privileges_label": "应用权限", + "scenes.app.popup.appsparameters.pages.app_update": "更新应用 {{$1}}(应用使用 {{$2}} 次。)", + "scenes.app.popup.appsparameters.pages.application_title": "应用", + "scenes.app.popup.appsparameters.pages.apps_title": "您的应用程序和连接器", + "scenes.app.popup.appsparameters.pages.automatique_label": "自动的", + "scenes.app.popup.appsparameters.pages.automatique_option_information": "如果您激活“自动”,此应用程序将自动添加到该公司的下一个工作区。", + "scenes.app.popup.appsparameters.pages.autorised_ip_adresses_label": "允许的 IP 地址", + "scenes.app.popup.appsparameters.pages.create_my_app": "创建我的应用程序", + "scenes.app.popup.appsparameters.pages.current_informations_apps_connectors": "您尚未创建应用程序。在创建应用程序或连接器之前,请确保它在我们的应用程序市场中尚不存在。", + "scenes.app.popup.appsparameters.pages.danger_zone_description": "删除申请", + "scenes.app.popup.appsparameters.pages.danger_zone_label": "危险地带", + "scenes.app.popup.appsparameters.pages.description_label": "描述", + "scenes.app.popup.appsparameters.pages.developped_apps_subtitle": "公司开发的应用", + "scenes.app.popup.appsparameters.pages.dispalyed_parameters_description": "允许您定义应用程序的可见位置。", + "scenes.app.popup.appsparameters.pages.displayed_parameters_label": "显示设置", + "scenes.app.popup.appsparameters.pages.filter_information": "此过滤器将 API 密钥的使用仅限于连接器中的服务器。", + "scenes.app.popup.appsparameters.pages.go_back": "后退", + "scenes.app.popup.appsparameters.pages.grp_section_name-error": "此名称已被另一个应用程序使用。请选择另一个。", + "scenes.app.popup.appsparameters.pages.grp_section_surname_label": "简化名称", + "scenes.app.popup.appsparameters.pages.installation": "安装。", + "scenes.app.popup.appsparameters.pages.instruction_message_twakecode": "首先以 JSON 格式编写消息。", + "scenes.app.popup.appsparameters.pages.interne_availability_application": "内部应用", + "scenes.app.popup.appsparameters.pages.json_configuration_information": "转到文档以生成 JSON 格式的配置。", + "scenes.app.popup.appsparameters.pages.loading": "正在加载...", + "scenes.app.popup.appsparameters.pages.message_data_next_event": "将在下一个 Event 中发送的被动数据", + "scenes.app.popup.appsparameters.pages.modify_public_data": "编辑应用程序的公共数据。", + "scenes.app.popup.appsparameters.pages.new_app_title": "新应用", + "scenes.app.popup.appsparameters.pages.ok_user_code": "好的", + "scenes.app.popup.appsparameters.pages.optimal_format": "最佳格式:48x48px。", + "scenes.app.popup.appsparameters.pages.parameters_form_small_text": "未发布的应用程序仅适用于您的公司。如果您想让所有 Twake 用户都可以使用它,请激活此选项。", + "scenes.app.popup.appsparameters.pages.public_availability_application": "公开申请", + "scenes.app.popup.appsparameters.pages.public_login_label": "公共标识符", + "scenes.app.popup.appsparameters.pages.publication_description": "确定应用程序的可见性。", + "scenes.app.popup.appsparameters.pages.publication_label": "出版物", + "scenes.app.popup.appsparameters.pages.publish_app_label": "发布应用", + "scenes.app.popup.userparameter.pages.keywords_notif_description": "突出显示以下关键字:", + "scenes.app.popup.userparameter.pages.mail_frequency_notif_configuration_description": "设置电子邮件通知的频率。", + "scenes.app.popup.userparameter.pages.private_message_content.show": "显示私信内容", + "scenes.app.popup.userparameter.pages.private_message_content.hide": "隐藏私信内容", + "scenes.app.popup.userparameter.pages.no_disturbing_notif_period_description": "选择您不接收通知的时间段。", + "scenes.app.popup.userparameter.pages.no_night_disturbing_label": "晚上请勿打扰", + "scenes.app.popup.userparameter.pages.notif_content_label": "通知内容", + "scenes.app.mainview.quick_search_placeholder": "快速搜索", + "scenes.app.popup.userparameter.personnal_workspaces_title": "您的工作空间", + "scenes.app.popup.workspaceparameter.admin_current_status": "您是管理员。", + "scenes.app.popup.workspaceparameter.admin_manager_current_status": "您是工作区管理员。", + "scenes.app.popup.workspaceparameter.manager_current_status": "您是公司管理员。", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace": "删除工作区", + "scenes.app.popup.workspaceparameter.pages.error_workspace_member": "您必须独自在工作区中才能将其删除。删除您的协作者,然后重试。", + "scenes.app.popup.workspaceparameter.pages.enter": "进入 ", + "scenes.app.popup.workspaceparameter.pages.description": "描述", + "scenes.app.popup.workspaceparameter.pages.developped_apps_small_text": "公司开发的应用", + "scenes.app.popup.workspaceparameter.pages.displayed_preferencies_subtitle": "显示首选项", + "scenes.app.popup.workspaceparameter.pages.install_button": "安装", + "scenes.app.popup.workspaceparameter.pages.installed_app_information": "在此工作区中安装应用程序。", + "scenes.app.popup.workspaceparameter.pages.installed_apps_information": "安装在此工作区中的应用程序 {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_message": "安装在公司其他领域的应用程序 {{$1}}", + "scenes.app.popup.workspaceparameter.pages.installed_apps_subtitle": "已安装的应用程序", + "scenes.app.popup.workspaceparameter.pages.invitation_error": "邀请以下用户时出错: ", + "scenes.app.popup.workspaceparameter.pages.invited_guest_check_message": "检查使用的用户名或电子邮件是否有效。", + "scenes.app.popup.workspaceparameter.pages.logo_modify_description": "编辑此工作区的图像", + "scenes.app.popup.workspaceparameter.pages.logo_subtitle": "标识", + "scenes.app.popup.workspaceparameter.pages.name_description": "更改此工作区的名称", + "scenes.app.popup.workspaceparameter.pages.name_label": "工作区名称", + "scenes.app.popup.workspaceparameter.pages.no_access": "没有访问权限。", + "scenes.app.popup.workspaceparameter.pages.title": "工作区设置", + "scenes.app.popup.workspaceparameter.pages.webhooks_access_subtitle": "访问网络钩子", + "scenes.apps.calendar.connectors_menu": "连接器...", + "scenes.apps.calendar.connectors_search_menu": "搜索连接器...", + "scenes.apps.calendar.create_calendar_title": "创建日历", + "scenes.apps.calendar.day_option": "日", + "scenes.apps.calendar.edit_calendar_title": "编辑日历", + "scenes.apps.calendar.export_title": "出口", + "scenes.apps.calendar.export_view_menu": "导出视图...", + "scenes.apps.calendar.ics_download_menu": "下载 ICS 文件", + "scenes.apps.calendar.ics_subscription_menu": "获取 ICS 订阅链接", + "scenes.apps.calendar.modals.advanced_options": "高级选项", + "scenes.apps.calendar.modals.description_placeholder": "描述", + "scenes.apps.calendar.modals.details_title": "细节", + "scenes.apps.calendar.modals.event_adresse_placeholder": "地址", + "scenes.apps.calendar.modals.event_description_placeholder": "描述", + "scenes.apps.calendar.modals.event_title_placeholder": "标题", + "scenes.apps.calendar.modals.modify_event_button": "编辑事件", + "scenes.apps.calendar.modals.part.participants": "参与者", + "scenes.apps.calendar.modals.participants_event": "参与者", + "scenes.apps.drive.message_added_file": "{{$1}} 发送 {{$2}}。", + "scenes.apps.drive.message_added_mutiple_files": "{{$1}} 发送了多个文件。", + "scenes.apps.drive.message_added_file_no_name": "{{$1}} 发送了一个文件。", + "scenes.apps.drive.choose_folder_button": "选择一个目录", + "scenes.apps.drive.choose_file_button": "选择一个文件", + "scenes.apps.drive.create_folder_button": "创建", + "scenes.apps.drive.download_button": "下载", + "scenes.apps.drive.open_link": "在新窗口中打开链接", + "scenes.apps.drive.files_subtitle": "文件", + "scenes.apps.drive.folder_subtitle": "文件夹", + "scenes.apps.drive.go_out_trash_menu": "留下垃圾", + "scenes.apps.drive.go_trash_menu": "去垃圾箱", + "scenes.apps.drive.import_from_computer_menu": "从电脑上传", + "scenes.apps.drive.move_text": "移动", + "scenes.apps.drive.new_file_menu": "新文件", + "scenes.apps.drive.new_file_title": "新文件", + "scenes.apps.drive.new_external_storage": "新的外部存储", + "scenes.apps.drive.new_folder_title": "新建文件夹", + "scenes.apps.drive.no_file_alert": "您没有允许您创建文件的应用程序。", + "scenes.apps.drive.no_storage_app_alert": "您没有允许添加外部存储的应用程序。", + "scenes.apps.drive.remove_definitely_menu": "永久删除", + "scenes.apps.drive.restore_menu": "恢复", + "scenes.apps.drive.throw_menu": "发送到垃圾箱", + "scenes.apps.drive.trash_empty_menu": "清空垃圾", + "scenes.apps.messages.message.modify_button": "编辑", + "scenes.apps.messages.message.pin_button": "置顶消息", + "scenes.app.popup.workspaceparameter.pages.cancel_invitation": "取消邀请", + "scenes.apps.account.account.fullname": "全名", + "login.email_login": "电子邮件/登录", + "scenes.apps.account.account.password_for_user": "您的用户的密码", + "scenes.apps.account.account.send_info": "将此凭据信息发送给您的用户。", + "scenes.apps.account.account.save": "保存帐号", + "components.workspace.list_manager.current_space": "当前工作空间", + "components.workspace.list_manager.all": "全部", + "components.searchpopup.loading": "加载更多结果", + "components.searchpopup.filter_ws": "过滤工作区", + "components.searchpopup.tags": "标签", + "components.searchpopup.size": "尺寸", + "components.searchpopup.creation": "创建", + "components.searchpopup.update_search": "更新搜索", + "components.searchpopup.last_modif": "最后修改", + "components.searchpopup.sender": "发件人", + "components.searchpopup.mentions": "提及", + "components.searchpopup.only_pinned": "仅固定消息", + "components.alert.confirm": "确认您的操作", + "components.alert.confirm_click": "单击“确定”确认您的操作。", + "components.searchpopup.tasks": "任务", + "scenes.app.mainview.advanced_search_placeholder": "高级搜索", + "components.searchpopup.hide_filters": "隐藏过滤器", + "components.searchpopup.show_filters": "显示过滤器", + "components.searchpopup.load_more": "加载更多结果", + "general.more": "更多的", + "scenes.apps.board.archived_tasks": "存档任务 ({{$1}})", + "scenes.apps.board.active_tasks": "活动任务", + "scenes.apps.board.kanban": "看板", + "components.userlistmanager.no_users": "没有用户。", + "scenes.apps.drive.used": "在这个文件夹中使用", + "scenes.apps.calendar.reminders": "提醒", + "scenes.app.popup.workspace.edit_temp": "编辑临时账户", + "scenes.app.popup.workspace.create_temp": "创建临时账户", + "scenes.apps.tasks.active_tasks": "活动任务", + "scenes.apps.drive.right_preview.versions": "版本", + "scenes.app.popup.appsparameters.pages.apps_connectors_small_text": "管理您的应用程序和连接器。", + "scenes.app.popup.appsparameters.pages.icon": "图标", + "scenes.app.popup.appsparameters.pages.title_informations": "基本信息", + "scenes.app.popup.appsparameters.pages.subtitle_informations": "与应用程序管理相关的信息", + "scenes.app.popup.appsparameters.pages.smalltext_user_id": "当前用户 ID", + "scenes.app.popup.appsparameters.pages.smalltext_workspace_id": "当前工作区 ID", + "scenes.app.popup.appsparameters.pages.smalltext_group_id": "当前组 ID", + "scenes.app.mainview.channel_description": "描述渠道", + "scenes.client.channelbar.channeltemplateeditor.checkbox": "自动邀请所有工作区用户加入此频道", + "scenes.client.channelbar.channelmemberslist.title": "{{$1}} 中的用户", + "scenes.client.channelbar.channelmemberslist.loader": "装载更多", + "scenes.client.channelbar.channelmemberslist.autocomplete": "添加或搜索用户", + "scenes.client.channelbar.channelmemberslist.menu.option_2": "从频道中删除", + "components.leftbar.channel.workspaceschannels.menu.option_1": "创建频道", + "components.leftbar.channel.workspaceschannels.menu.option_2": "加入频道", + "components.channelworkspacelist.title": "频道", + "scenes.client.channelbar.workspacechannellist.autocomplete": "搜索频道、用户或直接消息", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_creation": "创建一个新选项卡", + "scenes.client.mainview.tabs.tabstemplateeditor.title_tab_edition": "重命名 {{$1}}", + "components.connectorslistmanager.add_connectors": "添加连接器", + "components.newversion.new_version_component.row.part_2": "我们建议您重新加载应用程序并享受我们的新功能!", + "components.newversion.new_version_component.link": "单击此处重新加载", + "components.newversion.new_version_modal.title": "有新的更新可用 !", + "scenes.apps.drive.download_all_button": "全部下载", + "components.inputs.input_with_select.input.placeholder": "频道名称", + "components.inputs.input_with_select.select.placeholder": "栏目名称", + "components.inputs.input_with_select.select.no_sections": "开始写下您的第一个频道部分的名称。", + "components.inputs.input_with_select.button.tooltip": "设置频道部分", + "scenes.apps.messages.message.activity_message.a_added_b_to_the_channel": "{{$1}} 频道新增 {{$2}}", + "scenes.apps.messages.message.activity_message.a_removed_b_from_the_channel": "{{$1}} 从频道中移除 {{$2}}", + "scenes.apps.messages.message.activity_message.a_updated_channel_description": "{{$1}} 更改了描述", + "scenes.apps.messages.message.activity_message.a_updated_channel_name": "{{$1}} 将频道重命名为 {{$2}}", + "scenes.apps.messages.message.activity_message.a_created_channel_tab": "【X0X】新增【X19X】标签【X30X】", + "scenes.apps.messages.message.activity_message.a_deleted_channel_tab": "{{$1}} 移除 {{$2}} 选项卡 {{$3}}", + "scenes.apps.messages.message.activity_message.a_created_channel_connector": "{{$1}} 增加了一个新的连接器 {{$2}}", + "scenes.apps.messages.message.activity_message.a_deleted_channel_connector": "{{$1}} 移除了一个连接器 {{$2}}", + "scenes.client.channelbar.channelmemberslist.tag": "你", + "components.alert.leave_private_channel.title": "您确定要离开频道吗?", + "components.richtexteditor.toolbar.underline": "强调", + "components.richtexteditor.toolbar.italic": "斜体", + "components.richtexteditor.toolbar.strikethrough": "删除线", + "components.richtexteditor.toolbar.code": "代码", + "components.richtexteditor.toolbar.unordered-list": "项目符号列表", + "components.richtexteditor.toolbar.ordered-list": "有序列表", + "components.richtexteditor.toolbar.blockquote": "块引用", + "components.richtexteditor.toolbar.code-block": "代码块", + "components.locked_features.locked_history_banner.title": "您刚刚达到消息限制", + "components.locked_features.locked_history_banner.description": "贵公司有大量留言!立即升级以访问您的所有消息历史记录。", + "components.locked_features.locked_history_banner.button": "了解更多", + "components.locked_features.locked_guests_popup.title": "访客功能已锁定", + "components.locked_features.locked_guests_popup.subtitle": "此功能在 Twake 免费版中不可用", + "components.locked_features.locked_guests_popup.description": "哎哟!!似乎您想邀请外部用户加入您的工作区。如果您想与客人和外部合作伙伴协作,您可能需要考虑升级您的计划。探索我们的定价选项并为您的团队协作需求选择最佳选项。", + "components.locked_features.locked_guests_popup.learn_more_button": "了解更多", + "components.locked_features.locked_guests_popup.skip_for_now_button": "暂时跳过", + "components.on_boarding.popups.blocked_company.company_selector": "切换到另一家公司", + "scenes.apps.tasks.select_user_button": "查看其他用户的任务", + "scenes.apps.messages.input.attach_file.from_computer": "从电脑", + "scenes.app.popup.workspaceparameter.pages.table_title": "姓名", + "scenes.client.main_view.main_header.search_input": "搜索", + "scenes.apps.drive.new_link_title": "新链接", + "scenes.apps.drive.default_link_name": "无标题", + "components.emoji_picker.input_search_placeholder": "搜索", + "services.apps.messages.message_editor_service.upload_error_toaster": "{{$1}} - 您不能在消息中添加超过 {{$2}} 个文件", + "scenes.apps.messages.message.parts.deleted_content.text.current_user": "你删除了这条消息", + "scenes.apps.messages.message.parts.deleted_content.text": "{{$1}} 删除了他的消息", + "components.member.user_parts.and_more_user_text": " 和 {{$1}} 更多用户", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_link": "创建私人频道", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_text": " 反而", + "scenes.app.channelsbar.channelsuser.new_private_discussion.limit_reached_input_placeholder": "您添加的用户不能超过 10 个", + "general.uploading": "上传", + "components.locked_features.locked_workspace_popup.text": "哎哟!!您想在您的公司中创建一个新的工作空间吗?您可能需要考虑升级您的计划。探索我们的定价选项并为您的团队协作需求选择最佳选择。", + "components.locked_features.locked_only_office_popup.subtitle": "在免费版本中,您不能使用 onlyoffice。", + "components.locked_features.locked_only_office_popup.text": "哎哟!!似乎您想从 Twake 编辑文件。如果您想围绕办公文件进行协作,您可能需要考虑升级您的计划。探索我们的定价选项并为您的团队协作需求选择最佳选项。", + "components.locked_features.locked_drive_popup.title": "您刚刚达到驱动器限制", + "components.locked_features.locked_drive_popup.subtitle": "在免费版本中,您只能存储 6GB。", + "general.pause": "暂停", + "scenes.app.popup.appsparameters.pages.call_event_handlers": "事件类型为“{{$1}}”,id 为“{{$2}}”,被动为“{{$3}}”", + "scenes.app.popup.appsparameters.pages.company_label": "公司所有者", + "scenes.app.popup.appsparameters.pages.configuration_label": "配置", + "scenes.app.popup.appsparameters.pages.create_app_button": "创建应用程序", + "scenes.app.popup.appsparameters.pages.show_button": "展示", + "scenes.app.popup.appsparameters.pages.status_tilte": "状态", + "scenes.app.popup.appsparameters.pages.website_label": "网站", + "scenes.app.popup.workspaceparameter.pages.apps_company_small_text": "贵公司的应用", + "scenes.app.popup.workspaceparameter.pages.apps_connectors_title": "集成", + "scenes.app.popup.workspaceparameter.pages.apps_research_title": "搜索应用", + "scenes.app.popup.workspaceparameter.pages.apps_small_text": "此工作区的应用", + "scenes.app.popup.workspaceparameter.pages.configure_button": "配置", + "scenes.app.popup.workspaceparameter.pages.weight_max_small_text": "最大大小 5 MB。", + "scenes.app.popup.workspaceparameter.pages.withdraw_button": "从此工作区中删除", + "scenes.app.popup.workspaceparameter.pages.worspace_notif": "工作空间", + "scenes.app.popup.workspaceparameter.pages.write_access_subtitle": "写权限", + "scenes.app.popup.workspaceparameter.pages.your_apps_label": "您的应用", + "scenes.app.workspacesbar.components.change_company_title": "换公司", + "scenes.app.workspacesbar.components.create_company_menu": "创建公司", + "scenes.app.workspacesbar.components.grp_parameters": "{{$1}} 设置", + "scenes.apps.calendar.add_calendar_menu": "添加日历", + "scenes.apps.calendar.modals.reminders": "提醒事项", + "scenes.apps.calendar.no_calendar_text": "您尚未为此工作区设置任何日历。", + "scenes.apps.calendar.no_connectors_menu_text": "您没有任何可以连接到日历的连接器。", + "scenes.apps.calendar.remove_calendar_confirmation": "永久删除日历及其事件?", + "scenes.app.workspaces.components.skip": "跳过", + "scenes.app.taskpicker.select": "选择", + "components.drive.modify_uslist": "修改用户列表", + "components.workspace.list_manager.add": "添加工作区", + "scenes.apps.board.display_as": "显示为", + "scenes.apps.board.new_task": "+ 新任务", + "scenes.apps.board.all_boards": "所有板", + "components.alert.leave_private_channel.description": "除非有人邀请您,否则您将无法再次加入此私人频道。", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.tag": "你不是会员", + "components.verify_mail.text": "首先,您必须验证您的电子邮件地址。我们已将验证链接发送至", + "services.console_services.toaster.add_emails_error": "添加电子邮件时出错", + "services.console_services.toaster.success_verify_email": "验证链接已发送到您的电子邮件帐户", + "scenes.app.popup.workspaceparameter.edit_from_console": "在控制台中查看", + "services.console_services.toaster.success_invite_emails": "已成功添加 {{$1}} 个用户", + "scenes.client.channels_bar.modals.guest_management.title": "在 {{$1}} 中管理来宾", + "scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email": "邮件已发送", + "general.user.role.company.admin": "公司管理员", + "general.user.role.company.guest": "客人", + "general.user.deleted": "已删除帐户", + "components.richtexteditor.toolbar.bold": "胆大", + "components.locked_features.locked_guests_popup.or": "或者", + "components.on_boarding.popups.blocked_company.title": "您的公司因付款问题而被锁定", + "components.on_boarding.popups.blocked_company.company_subscription_plan_button": "点击这里", + "components.emoji_picker.categories.animals_and_nature": "动物与自然", + "components.emoji_picker.categories.food_and_drink": "食物和饮料", + "scenes.app.integrations_parameters.applications_table.search_placeholder": "搜索应用", + "scenes.app.integrations_parameters.company_application_popup.tag": "已安装", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.description_item": "描述", + "scenes.app.integrations_parameters.company_application_popup.tab_info.descriptions.website_item": "网站", + "scenes.app.integrations_parameters.company_applications_table.more_menu.show_application": "展示", + "app.state.recoil.hooks.use_current_company_applications.toaster_delete": "已成功从贵公司删除 {{$1}}", + "app.state.recoil.hooks.use_current_company_applications.toaster_add": "在贵公司成功添加【X19X】", + "scenes.apps.messages.input.replied_to": "回复 ", + "general.help.documentation": "文档", + "scenes.apps.calendar.event_edition.deadline_tag": "最后期限", + "scenes.apps.drive.left.search": "搜索", + "scenes.apps.parameters.group_sections.apps.badge_extension": "延期", + "scenes.apps.parameters.workspace_sections.members.members": "用户", + "scenes.apps.parameters.workspace_sections.members.pending": "待处理的电子邮件", + "scenes.apps.parameters.workspace_sections.members.invite": "邀请新用户", + "scenes.apps.tasks.list_modal.modify_list": "修改列表", + "scenes.apps.tasks.list_modal.new_list": "新名单", + "scenes.apps.tasks.list_modal.remove": "删除列表和任务", + "scenes.apps.tasks.list_modal.predefined_participants": "预定义参与者", + "scenes.apps.tasks.list_modal.archive_all_tasks": "归档所有任务", + "scenes.app.popup.appsparameters.pages._app_identity": "应用程序的身份", + "scenes.app.popup.appsparameters.pages._appareance_message_twakcode": "测试您的 Twacode 消息的外观", + "scenes.app.popup.appsparameters.pages.error_user_code": "错误", + "scenes.app.popup.appsparameters.pages.danger_zone_small_text": "如果此应用已发布,您将无法删除它。", + "scenes.app.popup.appsparameters.pages.error_app_simple_name_message": "您的应用程序的简化名称已被另一个应用程序使用。请改变它。", + "scenes.app.popup.appsparameters.pages.error_app_update_message": "更新应用程序时出错。", + "scenes.app.popup.appsparameters.pages.remove_app_button": "删除申请", + "scenes.app.popup.workspaceparameter.pages.read_access_subtitle": "读取权限", + "scenes.apps.drive.unconfigured_tab": "此选项卡尚未配置。", + "scenes.apps.drive.viewer.edit_with_button": "使用 {{$1}} 进行编辑", + "scenes.apps.drive.viewer.loading_preview_message": "正在加载...", + "scenes.apps.drive.viewer.no_preview_message": "无法查看此类文件。", + "scenes.login.verifymail.alert": "我们正在检查您的电子邮件!", + "scenes.login.verifymail.error_message": "发生错误", + "scenes.apps.drive.trash": "垃圾", + "scenes.tell_us": "请告诉我们你在做什么:", + "scenes.apps.drive.viewer.download_desktop": "下载 Twake Desktop 以在应用程序中进行预览", + "app.name.twake_drive": "文件", + "scenes.login.forgot_password.email_to_recover": "要恢复的电子邮件", + "scenes.login.forgot_password.mail_doesnt_exist": "此邮箱不存在", + "scenes.login.home.lost_password": "忘记密码?", + "scenes.login.home.create_account": "创建一个帐户", + "scenes.login.create_account.password": "密码", + "scenes.login.create_account.step_1_subtitle": "再简单不过了——我们只需要一些信息。", + "scenes.login.create_account.step_2_subtitle_a": "添加您的全名以便其他用户识别您。", + "scenes.login.create_account.step_2_subtitle_b": "您的电话号码保持私密。", + "app.name.twake_tasks": "任务", + "components.calendar.repetition.everyday": "日常的", + "components.calendar.repetition.does_not_repeat": "不重复", + "components.calendar.repetition.weekly_on": "每周 {{$1}}", + "components.calendar.repetition.monthly_on": "每月上 {{$1}} {{$2}}", + "components.calendar.repetition.monthly_on_day": "每月第 {{$1}}", + "components.calendar.repetition.annually_on": "每年在 {{$1}}", + "components.calendar.repetition.every_weekday": "每个工作日(周一至周五)", + "components.calendar.repetition.custom": "风俗...", + "components.calendar.repetition.repeat": "重复每", + "components.calendar.repetition.ends": "结束", + "components.calendar.repetition.never": "绝不", + "components.calendar.repetition.on": "在", + "components.calendar.repetition.after": "后", + "components.calendar.repetition.days": "天)", + "components.calendar.repetition.weeks": "周", + "components.calendar.repetition.months": "月", + "scenes.app.channelsbar.currentuser.user_parameter": "通知设置", + "components.emoji_picker.categories.smileys_and_people": "笑脸与人物", + "general.resume": "恢复", + "scenes.app.popup.workspaceparameter.pages.deleteworkspace_description": "要确认您要删除此工作区,请在下面键入名称并点击删除。", + "scenes.apps.messages.message.unpin_button": "取消固定消息", + "scenes.apps.messages.message.copy_link": "复制链接到消息", + "scenes.apps.messages.message.pinned": "固定", + "scenes.apps.messages.message.remove_button": "删除", + "scenes.apps.messages.message.reply_button": "回复", + "scenes.apps.messages.message.save_button": "节省", + "scenes.apps.messages.message.show_button": "展示", + "scenes.apps.messages.message.show_responses_button": "查看所有答案", + "scenes.apps.messages.message.types.first_channel_message_text": "这是频道的第一条消息", + "scenes.apps.messages.message.types.first_message_text": "这是第一条消息", + "scenes.apps.messages.messageslist.get_writing_user": "在写字...", + "scenes.apps.messages.messageslist.get_writing_users": "在写...", + "scenes.apps.messages.messageslist.go_last_message_button": "转到最后一条消息", + "scenes.apps.messages.messageslist.go_last_message_button.new_messages": "新消息", + "scenes.error_on_twake": "“休斯顿,我们有一个问题”", + "scenes.help_us": "但是,如果您想帮助我们解决此错误,请在下面给我们发送消息: ", + "scenes.apps.account.message_temporary": "临时帐户的工作方式与普通的 Twake 帐户类似,但您创建了密码,并且可以在必要时重置它。", + "scenes.apps.account.message_user_signin": "您的用户可以随时使用同一电子邮件登录并将临时帐户更改为普通帐户。", + "scenes.app.mainview.link_expired": "此公共链接无效或已过期。", + "scenes.app.mainview.create_account": "免费创建您的工作区 ", + "scenes.apps.calendar.modals.reminder_add": "添加提醒", + "scenes.apps.parameters.workspace_sections.members.invite_all": "邀请所有人", + "components.workspace.list_manager.current_company": "现任公司", + "components.workspace.calendar.invalid": "无效的", + "components.searchpopup.enter_text": "输入一些文本以搜索 Twake。", + "components.reminder.notification": "通知", + "components.reminder.minutes_bef": "几分钟前", + "components.reminder.hours_bef": "几小时前", + "components.reminder.days_bef": "几天前", + "components.reminder.weeks_bef": "几周前", + "components.reminder.by_email": "电子邮件", + "scenes.apps.calendar.video_link": "点击打开链接", + "scenes.app.mainview.discussion": "讨论", + "components.tagpicker.notag": "无标签", + "scenes.apps.tasks.modals.attachments": "附件", + "components.calendar.calendarselector.from": "从", + "scenes.apps.drive.move_text2": "移动", + "scenes.client.channelsbar.modals.workspace_channel_list.workspace_channel_row.loader": "装载更多", + "components.unverified_account.typography_text_danger": "您还有 {{$1}} 天的试用期。试用帐户将在 7 天后被冻结,并在注册 1 个月后永久删除。您可以通过单击我们发送给您的验证电子邮件中的“验证我的帐户”按钮来验证您的帐户。", + "components.unverified_account.verification_details": "我们已将验证详细信息发送至", + "components.account_verification_status_sentence": "您的帐户状态是:{{$1}}", + "components.account_verication_status_unverified": "未经证实", + "components.add_mails_workspace.button": "开始使用 Twake", + "components.add_mails_workspace.title_1": "添加一些用户", + "components.add_mails_workspace.title_2": "Twake 是一个团队协作工具,因此请邀请一些用户来测试我们为您创建的工作区。", + "components.add_mails_workspace.text_area_placeholder": "输入您的用户的电子邮件*", + "components.verify_mail.title_1": "恭喜", + "components.verify_mail.title_2": "您现在是 Twake 的正式用户!", + "components.verify_mail.button": "添加用户", + "general.user.role.company.member": "成员", + "components.on_boarding.popups.blocked_company.or": "或者", + "scenes.apps.tasks.select_user": "搜索用户", + "components.emoji_picker.categories.not_found": "未找到表情符号", + "components.locked_features.locked_workspace_popup.subtitle": "在免费版本中,您的公司中只能拥有一个工作区。", + "components.locked_features.locked_only_office_popup.title": "您无法编辑此文件", + "'": "'", + "scenes.apps.messages.message.types.no_message_in_thread": "还没有人回复。", + "login.create_account": "创建账户", + "login.login_error": "登录时出错", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.label": "默认工作区", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.unknown": "未知错误", + "\"": "”", + "scenes.app.workspaces.welcome_page.no_workspace_subtitle": "还没有人邀请您到工作区。", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.default_workspace.description": "自动邀请所有工作区用户加入此频道", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.title": "您即将删除 {{$1}}", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.alert_total_members": "您在 {{$2}} 中仍有 {{$1}} 成员。您应该删除所有成员才能删除此工作区。", + "scenes.app.popup.workspaceparameter.pages.delete_workspace_popup.checkbox": "我了解我工作区的所有消息和文件都将被删除。", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.max_size": "最大徽标大小为 5mb", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.bad_format": "格式错误,只允许使用 png gif 和 jpg", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.error.prefix": "错误", + "scenes.app.channelsbar.currentuser.reset": "重启", + "components.rich_text_editor.plugins.suggestions.default_message.display_results": "至少写三个字母来显示用户", + "components.rich_text_editor.plugins.suggestions.default_message.no_user_found": "未找到用户", + "components.rich_text_editor.plugins.suggestions.default_message.no_emoji_found": "未找到表情符号", + "components.rich_text_editor.plugins.suggestions.default_message.no_command_found": "未找到命令", + "scenes.app.messages.input.parts.is_writing.message.users_and_more_are_writing": "{{$1}}、{{$2}} 和 {{$3}} 更多用户正在写...", + "scenes.app.messages.input.parts.is_writing.message.user_is_writing": "{{$1}} 正在写...", + "scenes.app.messages.input.parts.is_writing.message.users_are_writing": "{{$1}} 和 {{$2}} 正在写入...", + "components.locked_features_components.locked_invite_alert.message_link": "升级您的公司", + "components.locked_features_components.locked_invite_alert.message_magic_link": " 联系您公司的所有者或管理员。", + "components.locked_features_components.locked_invite_alert.message_part_1": "贵公司已达到 {{$1}} 成员的最大限制。请 ", + "components.locked_features_components.locked_invite_alert.message_part_2": " 邀请更多成员。", + "views.client.popup.workspace_parameter.pages.workspace_members.link_to_console": "在控制台上查看我的所有公司成员", + "twake.application.access.title": "为您的应用选择正确的范围。", + "twake.application.access.no_default_scopes_available'": "此集成没有任何 {{$1}} 访问权限", + "scenes.app.popup.appsparameters.pages.application_editor.application_published": "{{$1}}申请成功!", + "scenes.app.integrations_parameters.add_application": "新整合", + "scenes.app.integrations_parameters.company_applications_table.more_menu.developer_settings": "开发者设置", + "scenes.app.popup.appsparameters.pages.amazing_app_description": "用几句话描述您的应用程序", + "scenes.app.popup.appsparameters.pages.application_creator.title": "新整合", + "scenes.app.popup.appsparameters.pages.application_creator.checkbox": "我了解该公司的所有者和管理员将能够修改和发布此应用程序。", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed": "成功删除应用程序 {{$1}} !", + "scenes.app.popup.appsparameters.pages.application_editor.application_removed_error": "删除应用程序 {{$1}} 时出错!", + "scenes.app.popup.appsparameters.pages.application_editor.help_link": "Twake API 文档", + "scenes.app.popup.appsparameters.pages.application_editor.help_text": "如果您不知道如何填写这些,请访问 ", + "scenes.app.popup.appsparameters.pages.app.private_key": "私钥", + "components.rich_text_editor.plugins.suggestions.loading": "寻找更多", + "components.open_desktop_popup.subtitle": "在 Twake 應用中打開", + "components.open_desktop_popup.open_here_link": "改為在此處打開", + "molecules.download_banner.title": "充分利用 twake,立即下载桌面应用程序", + "molecules.download_banner.download_button": "下载桌面应用程序", + "scenes.app.channelsbar.channel_copy_link": "复制频道链接", + "scenes.app.popup.workspaceparameter.pages.workspace_identity.toaster.success.update": "成功更新", + "components.searchpopup.recent_media": "近期媒体", + "components.searchpopup.recent_files": "最近的文件", + "components.searchpopup.no_results_for": "没有结果", + "components.searchpopup.try_new_search": "尝试新的搜索", + "components.searchpopup.all": "全部", + "components.searchpopup.chats": "聊天", + "components.searchpopup.media": "媒体", + "components.searchpopup.files": "文件", + "components.searchpopup.recent_chats": "最近的聊天", + "components.searchpopup.recent_channels_and_contacts": "最近的频道和联系人", + "components.searchpopup.header_title": "搜索", + "components.searchpopup.scope.company": "在所有公司", + "components.searchpopup.scope.channel": "在这个频道", + "components.searchpopup.channels": "频道", + "components.searchpopup.messages": "留言" +} diff --git a/twake/frontend/public/public/font/inter/Inter-Black.woff b/twake/frontend/public/public/font/inter/Inter-Black.woff new file mode 100644 index 0000000000..a18593a096 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Black.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Black.woff2 b/twake/frontend/public/public/font/inter/Inter-Black.woff2 new file mode 100644 index 0000000000..68f64c9ed9 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Black.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff b/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff new file mode 100644 index 0000000000..b6b01943d9 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff2 new file mode 100644 index 0000000000..1c9c7ca8b0 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-BlackItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Bold.woff b/twake/frontend/public/public/font/inter/Inter-Bold.woff new file mode 100644 index 0000000000..eaf3d4bfd7 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Bold.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Bold.woff2 b/twake/frontend/public/public/font/inter/Inter-Bold.woff2 new file mode 100644 index 0000000000..2846f29cc8 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Bold.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff b/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff new file mode 100644 index 0000000000..3275076164 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff2 new file mode 100644 index 0000000000..0b1fe8e125 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-BoldItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff b/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff new file mode 100644 index 0000000000..c2c17edead Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff2 b/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff2 new file mode 100644 index 0000000000..c24c2bdc2f Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraBold.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff b/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff new file mode 100644 index 0000000000..c42f70526c Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff2 new file mode 100644 index 0000000000..4a81dc7982 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraBoldItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff b/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff new file mode 100644 index 0000000000..d0de5f3973 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff2 b/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff2 new file mode 100644 index 0000000000..f2ea706faf Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraLight.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff b/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff new file mode 100644 index 0000000000..81f1a28ef5 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff2 new file mode 100644 index 0000000000..9af717ba91 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ExtraLightItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Italic.woff b/twake/frontend/public/public/font/inter/Inter-Italic.woff new file mode 100644 index 0000000000..a806b38201 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Italic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Italic.woff2 b/twake/frontend/public/public/font/inter/Inter-Italic.woff2 new file mode 100644 index 0000000000..a619fc5486 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Italic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Light.woff b/twake/frontend/public/public/font/inter/Inter-Light.woff new file mode 100644 index 0000000000..c496464d02 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Light.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Light.woff2 b/twake/frontend/public/public/font/inter/Inter-Light.woff2 new file mode 100644 index 0000000000..bc4be6658b Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Light.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-LightItalic.woff b/twake/frontend/public/public/font/inter/Inter-LightItalic.woff new file mode 100644 index 0000000000..f84a9de35e Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-LightItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-LightItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-LightItalic.woff2 new file mode 100644 index 0000000000..842b2dfcb7 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-LightItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Medium.woff b/twake/frontend/public/public/font/inter/Inter-Medium.woff new file mode 100644 index 0000000000..d546843f28 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Medium.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Medium.woff2 b/twake/frontend/public/public/font/inter/Inter-Medium.woff2 new file mode 100644 index 0000000000..f92498a2ec Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Medium.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff b/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff new file mode 100644 index 0000000000..459a656889 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff2 new file mode 100644 index 0000000000..0e3019f4ae Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-MediumItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Regular.woff b/twake/frontend/public/public/font/inter/Inter-Regular.woff new file mode 100644 index 0000000000..62d3a61871 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Regular.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Regular.woff2 b/twake/frontend/public/public/font/inter/Inter-Regular.woff2 new file mode 100644 index 0000000000..6c2b6893d5 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Regular.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-SemiBold.woff b/twake/frontend/public/public/font/inter/Inter-SemiBold.woff new file mode 100644 index 0000000000..a815f43a91 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-SemiBold.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-SemiBold.woff2 b/twake/frontend/public/public/font/inter/Inter-SemiBold.woff2 new file mode 100644 index 0000000000..611e90c958 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-SemiBold.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff b/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff new file mode 100644 index 0000000000..909e43a97d Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff2 new file mode 100644 index 0000000000..545685bd2c Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-SemiBoldItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-Thin.woff b/twake/frontend/public/public/font/inter/Inter-Thin.woff new file mode 100644 index 0000000000..62bc58cd14 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Thin.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-Thin.woff2 b/twake/frontend/public/public/font/inter/Inter-Thin.woff2 new file mode 100644 index 0000000000..abbc3a5c96 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-Thin.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff b/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff new file mode 100644 index 0000000000..700a7f069b Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff differ diff --git a/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff2 b/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff2 new file mode 100644 index 0000000000..ab0b2002a3 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-ThinItalic.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-italic.var.woff2 b/twake/frontend/public/public/font/inter/Inter-italic.var.woff2 new file mode 100644 index 0000000000..b826d5af84 Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-italic.var.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter-roman.var.woff2 b/twake/frontend/public/public/font/inter/Inter-roman.var.woff2 new file mode 100644 index 0000000000..6a256a068f Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter-roman.var.woff2 differ diff --git a/twake/frontend/public/public/font/inter/Inter.var.woff2 b/twake/frontend/public/public/font/inter/Inter.var.woff2 new file mode 100644 index 0000000000..365eedc50c Binary files /dev/null and b/twake/frontend/public/public/font/inter/Inter.var.woff2 differ diff --git a/twake/frontend/public/public/font/inter/inter.css b/twake/frontend/public/public/font/inter/inter.css new file mode 100644 index 0000000000..f450010124 --- /dev/null +++ b/twake/frontend/public/public/font/inter/inter.css @@ -0,0 +1,200 @@ +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 100; + font-display: swap; + src: url("Inter-Thin.woff2?v=3.19") format("woff2"), + url("Inter-Thin.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 100; + font-display: swap; + src: url("Inter-ThinItalic.woff2?v=3.19") format("woff2"), + url("Inter-ThinItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 200; + font-display: swap; + src: url("Inter-ExtraLight.woff2?v=3.19") format("woff2"), + url("Inter-ExtraLight.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 200; + font-display: swap; + src: url("Inter-ExtraLightItalic.woff2?v=3.19") format("woff2"), + url("Inter-ExtraLightItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 300; + font-display: swap; + src: url("Inter-Light.woff2?v=3.19") format("woff2"), + url("Inter-Light.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 300; + font-display: swap; + src: url("Inter-LightItalic.woff2?v=3.19") format("woff2"), + url("Inter-LightItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url("Inter-Regular.woff2?v=3.19") format("woff2"), + url("Inter-Regular.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 400; + font-display: swap; + src: url("Inter-Italic.woff2?v=3.19") format("woff2"), + url("Inter-Italic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url("Inter-Medium.woff2?v=3.19") format("woff2"), + url("Inter-Medium.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 500; + font-display: swap; + src: url("Inter-MediumItalic.woff2?v=3.19") format("woff2"), + url("Inter-MediumItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url("Inter-SemiBold.woff2?v=3.19") format("woff2"), + url("Inter-SemiBold.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 600; + font-display: swap; + src: url("Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"), + url("Inter-SemiBoldItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url("Inter-Bold.woff2?v=3.19") format("woff2"), + url("Inter-Bold.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 700; + font-display: swap; + src: url("Inter-BoldItalic.woff2?v=3.19") format("woff2"), + url("Inter-BoldItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 800; + font-display: swap; + src: url("Inter-ExtraBold.woff2?v=3.19") format("woff2"), + url("Inter-ExtraBold.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 800; + font-display: swap; + src: url("Inter-ExtraBoldItalic.woff2?v=3.19") format("woff2"), + url("Inter-ExtraBoldItalic.woff?v=3.19") format("woff"); +} + +@font-face { + font-family: 'Inter'; + font-style: normal; + font-weight: 900; + font-display: swap; + src: url("Inter-Black.woff2?v=3.19") format("woff2"), + url("Inter-Black.woff?v=3.19") format("woff"); +} +@font-face { + font-family: 'Inter'; + font-style: italic; + font-weight: 900; + font-display: swap; + src: url("Inter-BlackItalic.woff2?v=3.19") format("woff2"), + url("Inter-BlackItalic.woff?v=3.19") format("woff"); +} + +/* ------------------------------------------------------- +Variable font. +Usage: + + html { font-family: 'Inter', sans-serif; } + @supports (font-variation-settings: normal) { + html { font-family: 'Inter var', sans-serif; } + } +*/ +@font-face { + font-family: 'Inter var'; + font-weight: 100 900; + font-display: swap; + font-style: normal; + font-named-instance: 'Regular'; + src: url("Inter-roman.var.woff2?v=3.19") format("woff2"); +} +@font-face { + font-family: 'Inter var'; + font-weight: 100 900; + font-display: swap; + font-style: italic; + font-named-instance: 'Italic'; + src: url("Inter-italic.var.woff2?v=3.19") format("woff2"); +} + + +/* -------------------------------------------------------------------------- +[EXPERIMENTAL] Multi-axis, single variable font. + +Slant axis is not yet widely supported (as of February 2019) and thus this +multi-axis single variable font is opt-in rather than the default. + +When using this, you will probably need to set font-variation-settings +explicitly, e.g. + + * { font-variation-settings: "slnt" 0deg } + .italic { font-variation-settings: "slnt" 10deg } + +*/ +@font-face { + font-family: 'Inter var experimental'; + font-weight: 100 900; + font-display: swap; + font-style: oblique 0deg 10deg; + src: url("Inter.var.woff2?v=3.19") format("woff2"); +} diff --git a/twake/frontend/public/public/img/hexagon.png b/twake/frontend/public/public/img/hexagon.png new file mode 100644 index 0000000000..354acbb031 Binary files /dev/null and b/twake/frontend/public/public/img/hexagon.png differ diff --git a/twake/frontend/public/public/img/logo/128x128.png b/twake/frontend/public/public/img/logo/128x128.png new file mode 100644 index 0000000000..b6bffc97b8 Binary files /dev/null and b/twake/frontend/public/public/img/logo/128x128.png differ diff --git a/twake/frontend/public/public/img/logo/16x16.png b/twake/frontend/public/public/img/logo/16x16.png new file mode 100644 index 0000000000..820b375edf Binary files /dev/null and b/twake/frontend/public/public/img/logo/16x16.png differ diff --git a/twake/frontend/public/public/img/logo/256x256.png b/twake/frontend/public/public/img/logo/256x256.png new file mode 100644 index 0000000000..caf50a8fb5 Binary files /dev/null and b/twake/frontend/public/public/img/logo/256x256.png differ diff --git a/twake/frontend/public/public/img/logo/32x32.png b/twake/frontend/public/public/img/logo/32x32.png new file mode 100644 index 0000000000..e28beb27f5 Binary files /dev/null and b/twake/frontend/public/public/img/logo/32x32.png differ diff --git a/twake/frontend/public/public/img/logo/64x64.png b/twake/frontend/public/public/img/logo/64x64.png new file mode 100644 index 0000000000..6bfdf13b00 Binary files /dev/null and b/twake/frontend/public/public/img/logo/64x64.png differ diff --git a/twake/frontend/public/public/sounds/belligerent.wav b/twake/frontend/public/public/sounds/belligerent.wav new file mode 100644 index 0000000000..5790c2a4be Binary files /dev/null and b/twake/frontend/public/public/sounds/belligerent.wav differ diff --git a/twake/frontend/public/public/sounds/chord.wav b/twake/frontend/public/public/sounds/chord.wav new file mode 100644 index 0000000000..9209784324 Binary files /dev/null and b/twake/frontend/public/public/sounds/chord.wav differ diff --git a/twake/frontend/public/public/sounds/newnotification.wav b/twake/frontend/public/public/sounds/newnotification.wav old mode 100755 new mode 100644 index 1620b41f8c..97e443dd99 Binary files a/twake/frontend/public/public/sounds/newnotification.wav and b/twake/frontend/public/public/sounds/newnotification.wav differ diff --git a/twake/frontend/public/public/sounds/polite.wav b/twake/frontend/public/public/sounds/polite.wav new file mode 100644 index 0000000000..198dcbb6a7 Binary files /dev/null and b/twake/frontend/public/public/sounds/polite.wav differ diff --git a/twake/frontend/scripts/find_non_translated_fields.py b/twake/frontend/scripts/find_non_translated_fields.py deleted file mode 100644 index 1849ac65f9..0000000000 --- a/twake/frontend/scripts/find_non_translated_fields.py +++ /dev/null @@ -1,66 +0,0 @@ -import os -import re - -rootpath = os.path.abspath('../frontend/src/app') - -def nextGuillemet(s, i): - for k in range(i , len(s)): - if s[k]== '"': - return k - return len(s) - -def isRelevant(phrase): - #if len(phrase) > 0 and phrase[0].isupper(): - # return True - cpt = 0 - espace = 0 - nblet = 0 - for k in range(len(phrase)): - letter = phrase[k] - if letter.isalpha(): - nblet +=1 - if letter.isupper(): - if k>0 and phrase[k-1].islower(): - cpt-=500 - else: - cpt += 1 - elif letter == ' ': - espace +=1 - elif letter == '_': - nblet-=500 - return len(phrase)>espace>=0 and cpt>0 and nblet+espace > len(phrase)*0.88 - #return phrase.startswith("Vous êtes") - -#print(os.listdir(rootpath)) - -ecriture = open('../fichier-parcours.txt', "w") - -for dossier, sous_dossiers, fichiers in os.walk(rootpath): - for fichier in fichiers: - currentpath = os.path.join(dossier, fichier) - if currentpath.endswith(".js") and (currentpath.count(".")==1): - #print(currentpath) - if currentpath.__contains__("languages"): - continue - - lecture = open(currentpath, "r") - s = lecture.read() - spl = re.compile(r'["]') - #t = s.split('"')[1:] - t = spl.split(s) - for k in range(1,len(t),2): - - if isRelevant(t[k]): - if k+1>=len(t) or not re.match(r'( *\)|, *\n *\))', t[k+1]): - ecriture.write(currentpath +" : "+ t[k] + "\n") - t = re.findall('>[^<]*<', s) - for k in range(len(t)): - if isRelevant(t[k]): - ecriture.write(currentpath +" : "+ t[k] + "\n") - t = re.findall('\'[^"]*\'', s) - for k in range(len(t)): - if isRelevant(t[k]): - ecriture.write(currentpath +" : "+ t[k] + "\n") - - lecture.close() -ecriture.close() diff --git a/twake/frontend/scripts/formatFilesAndFolders.js b/twake/frontend/scripts/formatFilesAndFolders.js new file mode 100755 index 0000000000..29b938c00e --- /dev/null +++ b/twake/frontend/scripts/formatFilesAndFolders.js @@ -0,0 +1,143 @@ +const fs = require('fs'); +const Path = require('path'); +const _ = require('lodash'); + +const appUrl = '../src/app'; +const componentsUrl = `${appUrl}/components`; +const modelsUrl = `${appUrl}/models`; +const scenesUrl = `${appUrl}/scenes`; +const servicesUrl = `${appUrl}/services`; + +const routes = new Map(); + +const isDirectory = path => fs.lstatSync(path).isDirectory(); + +// pwd must start with 'src/...' +const getAbsolutePath = (path, pwd = appUrl) => { + if (path[0] === '.') { + const mergePath = Path.resolve(pwd, path); + + console.log({ pwd, path, resolve: mergePath }); + return mergePath; + } + + path = path.replace(/^app\//, appUrl + '/'); + path = path.replace(/^environment\//, appUrl + '/environment/'); + path = path.replace(/^common\//, appUrl + '/common/'); + path = path.replace(/^components\//, appUrl + '/components/'); + path = path.replace(/^services\//, appUrl + '/services/'); + path = path.replace(/^scenes\//, appUrl + '/scenes/'); + path = path.replace(/^apps\//, appUrl + '/apps/'); + + return Path.resolve(path); +}; +const renameItem = item => { + // Keywords that should be skipped + const toSkip = [ + '.', + '..', + 'feather', + 'README.md', + 'react-feather', + 'unicons.eot', + 'unicons.svg', + 'unicons.ttf', + 'unicons.woff', + 'unicons.woff2', + ]; + + const name = item.split('.')[0]; + const extension = item.split('.')[1] ? `.${item.split('.')[1]}` : undefined; + + return toSkip.includes(item) + ? item + : `${_.lowerCase(name).replace(/ /g, '-')}${extension ? extension : ''}`; +}; + +const updateMap = (rootUrl, fileOrFolderPath = false) => { + let newFileOrFolderPath = rootUrl; + if (fileOrFolderPath) { + const oldFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`; + newFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`; + routes.set(getAbsolutePath(oldFileOrFolderPath, '.'), true); + } + + if (isDirectory(newFileOrFolderPath)) { + const files = fs.readdirSync(newFileOrFolderPath); + files.forEach(fileOrFolderPath => { + updateMap(newFileOrFolderPath, fileOrFolderPath); + }); + } +}; + +const processRename = (rootUrl, fileOrFolderPath = false) => { + let newFileOrFolderPath = rootUrl; + + if (fileOrFolderPath) { + const newFileOrFolderName = renameItem(fileOrFolderPath); + const oldFileOrFolderPath = `${rootUrl}/${fileOrFolderPath}`; + newFileOrFolderPath = `${rootUrl}/${newFileOrFolderName}`; + + fs.renameSync(oldFileOrFolderPath, newFileOrFolderPath); + } + + if (isDirectory(newFileOrFolderPath)) { + const files = fs.readdirSync(newFileOrFolderPath); + files.forEach(fileOrFolderPath => { + processRename(newFileOrFolderPath, fileOrFolderPath); + }); + } +}; + +const recursiveWatchingImports = (rootPath, fileOrFolderPath = false) => { + const nextPath = fileOrFolderPath ? `${rootPath}/${fileOrFolderPath}` : rootPath; + if (!isDirectory(nextPath)) { + let content = fs.readFileSync(nextPath, { encoding: 'utf-8' }); + + if (nextPath.includes('/environment/')) { + return; + } + + const importedPaths = Array.from( + content.matchAll(/^(import|export .*?from) .*?('|")(.*?)('|").*?$/gm), + ).map(s => s[3]); + + importedPaths.forEach(path => { + const absolutePath = getAbsolutePath(path, rootPath); + + //Test if absolutePath is in map + if ( + routes.has(absolutePath) || + routes.has(absolutePath + '.js') || + routes.has(absolutePath + '.jsx') || + routes.has(absolutePath + '.ts') || + routes.has(absolutePath + '.tsx') || + routes.has(absolutePath + '.scss') || + routes.has(absolutePath + '.less') + ) { + const newPath = path.split('/').map(renameItem).join('/'); + content = content.replace(path, newPath); + } + }); + + fs.writeFileSync(nextPath, content); + } else { + const files = fs.readdirSync(nextPath); + files.forEach(fileOrFolderPath => { + recursiveWatchingImports(nextPath, fileOrFolderPath); + }); + } +}; + +const cleanFiles = async () => { + //Fill up map with all the files we gonna rename + updateMap(componentsUrl); + + // Now we should look at each files to see if there is a match with the previous changes and modify the related imports + recursiveWatchingImports(appUrl); + + //Rename files and folders recursivelly + processRename(componentsUrl); +}; + +cleanFiles(); diff --git a/twake/frontend/scripts/redundances_lan_fields.py b/twake/frontend/scripts/redundances_lan_fields.py deleted file mode 100644 index 827c4792d8..0000000000 --- a/twake/frontend/scripts/redundances_lan_fields.py +++ /dev/null @@ -1,68 +0,0 @@ -import use_of_the_lan_fields as sc - -import os -import sys - -sc.init() -items = sc.dicstr.items() - -dicrep = dict() - -def update_rep(key, val): - if key in dicrep: - v = dicrep.get(key) - if not (val in v): - v.append(val) - else: - dicrep.update([(key,[val])]) -def redundance(): - for (k1, v1) in items: - for (k2, v2) in items: - if k1!=k2:# and v1[-1]!='': - b= True - for l in range(len(min(v1,v2))): - b = b and v1[l] == v2[l] - if b: - update_rep(v1[-1],k1) - -def overwrite(): - #overwriting - meta = [item for sublist in [it for it in dicrep.values()] for item in sublist] - print(meta) - for dossier, sous_dossiers, fichiers in os.walk(sc.rootpath): - for fichier in fichiers: - currentpath = os.path.join(dossier, fichier) - if currentpath.endswith(".js") and (currentpath.count(".")==1): - if currentpath.__contains__("languages"): - continue - b = False - - lecture = open(currentpath, "r+") - s = lecture.read() - - t = s.split("'")[1::2] - for sub in t: - if sub in meta: - #replace sub by dicrep[sub][0] in file - en_sub = sc.dicstr.get(sub)[-1] - if len(dicrep.get(en_sub))>3 and en_sub: - repsub = dicrep.get(en_sub)[0] - s = s.replace(sub, repsub) - b = True - if b: - print('Begin Lecture') - lecture.seek(0) - lecture.write(s) - print("Changed: " + currentpath) - lecture.close() - -redundance() -ecriture = open('../fichier3.txt', "w") -c=0 -for key, value in dicrep.items(): - if len(value)>3 and key: - c+= len(value) - ecriture.write(key + " : "+ str(value)+" " + str(len(value))+ "\n") -ecriture.write(str(c)) -ecriture.close() -overwrite() diff --git a/twake/frontend/scripts/use_of_the_lan_fields.py b/twake/frontend/scripts/use_of_the_lan_fields.py deleted file mode 100644 index cfc662b9da..0000000000 --- a/twake/frontend/scripts/use_of_the_lan_fields.py +++ /dev/null @@ -1,97 +0,0 @@ -import os -import re - -rootpath = os.path.abspath('..') -#2 dictionnaries : 1 with the nb of occurences, 1 with the strings in the various languages - -dicoc = dict() -dicstr = dict() - -def update_dic(dic, key, val): - if key in dic: - v = dic.get(key) - v.append(val) - else: - dic.update([(key,[val])]) - #print(dicstr.get(key)) - -def update_oc(key): - if key in dicoc: - v = dicoc.get(key) - dicoc.update([(key , v+1)]) - else: - dicoc.update([(key,1)]) - #print(dicoc.get(key)) - -def get_string(s): - if s.__contains__('"'): - return s.split('"')[1] - elif s.__contains__("'"): - return s.split("'")[1] - else: - return s - -#print(os.listdir(rootpath)) - -def init(): - - #initialization of the strings dictionnaries - for dossier, sous_dossiers, fichiers in os.walk(rootpath + "/frontend/src/app/services/languages/locale/"): - for fichier in fichiers: - currentpath = os.path.join(dossier, fichier) - if currentpath.endswith(".js") and (currentpath.count(".")==1) and 'ja' not in currentpath and not currentpath.endswith('es.js'): - - lecture = open(currentpath, "r") - s = lecture.read() - - t = s.splitlines() - k= 1 - while k < len(t): - if t[k].__contains__(':'): - l = t[k].split(':') - key = get_string(l[0]) - if l[1] == '': - value = get_string(t[k+1]) - k+=2 - else: - value = get_string(l[1]) - k+=1 - update_dic(dicstr, key,value) - dicoc.update([(key,0)]) - else: - k+=1 - - - lecture.close() - - -def count(): - #counting occurences - for dossier, sous_dossiers, fichiers in os.walk(rootpath): - for fichier in fichiers: - currentpath = os.path.join(dossier, fichier) - if currentpath.endswith(".js") and (currentpath.count(".")==1): - if currentpath.__contains__("languages"): - continue - - lecture = open(currentpath, "r") - s = lecture.read() - - t = s.split("'")[1::2] - for sub in t: - if sub in dicoc: - update_oc(sub) - lecture.close() - - -def main(): - init() - count() - ecriture = open('../fichier2.txt', "w") - for key, value in dicstr.items(): - if (len(value)<3 or '' in value or 'No traduction'in value) and dicoc[key] >= 0: - ecriture.write(key + " : "+ str(value)+" "+ str(dicoc[key]) + "\n") - ecriture.close() - #print(dicstr) -main() - diff --git a/twake/frontend/src/app/app.tsx b/twake/frontend/src/app/app.tsx index f33a76ebd3..8600a9b719 100755 --- a/twake/frontend/src/app/app.tsx +++ b/twake/frontend/src/app/app.tsx @@ -4,15 +4,17 @@ import { Router } from 'react-router'; import { Switch, Route } from 'react-router-dom'; import { RecoilRoot } from 'recoil'; -import Integration from 'app/scenes/Integration/Integration'; -import RouterServices, { RouteType } from './services/RouterService'; -import ErrorBoundary from 'app/scenes/Error/ErrorBoundary'; -import InitService from './services/InitService'; -import useTimeout from './services/hooks/useTimeout'; -import ApplicationLoader from './components/Loader/ApplicationLoader'; +import MobileRedirect from './views/mobile-redirect'; +import Integration from 'app/views/integration'; +import RouterServices, { RouteType } from './features/router/services/router-service'; +import ErrorBoundary from 'app/views/error/error-boundary'; +import InitService from './features/global/services/init-service'; +import useTimeout from 'app/features/global/hooks/use-timeout'; +import ApplicationLoader from './components/loader/application-loader'; -import 'app/ui.scss'; -import 'app/theme.less'; +import DebugState from './components/debug/debug-state'; +import 'app/styles/index.less'; +import DesktopRedirect from './views/desktop-redirect'; const delayMessage = 5000; @@ -37,7 +39,9 @@ export default () => { setDisplayDelayLoader(false); try { window.document.getElementById('app_loader')?.remove(); - } catch (err) {} + } catch (err) { + //Null + } } }, [server_infos_loaded]); @@ -51,41 +55,46 @@ export default () => { return ( - - - - {RouterServices.routes.map((route: RouteType, index: number) => ( - - route.options?.withErrorBoundary ? ( - - - - ) : ( - - ) + + + + + + + {RouterServices.routes.map((route: RouteType, index: number) => ( + + route.options?.withErrorBoundary ? ( + + + + ) : ( + + ) + } + /> + ))} + { + { + RouterServices.replace( + `${ + RouterServices.pathnames.LOGIN + }?auto&${RouterServices.history.location.search.substr(1)}`, + ); + return
; + }} + /> } - /> - ))} - { - { - RouterServices.replace( - `${ - RouterServices.pathnames.LOGIN - }?auto&${RouterServices.history.location.search.substr(1)}`, - ); - return
; - }} - /> - } - - - + + + + + ); }; diff --git a/twake/frontend/src/app/atoms/_avatar/avatar.tsx b/twake/frontend/src/app/atoms/_avatar/avatar.tsx new file mode 100644 index 0000000000..b4c84631f7 --- /dev/null +++ b/twake/frontend/src/app/atoms/_avatar/avatar.tsx @@ -0,0 +1,43 @@ +import _ from 'lodash'; + +export default function Avatar( + props: any & { + avatar: string; + size: 28 | 14 | 48; + }, +) { + const size = props.size || 14; + const className = + ' inline-block h-' + + size + + ' w-' + + size + + ' rounded-full overflow-hidden bg-zinc-200 ' + + (props.className || ''); + + if (props.avatar || props.src) { + return ( +
+ ); + } + + return ( + + + + + + ); +} diff --git a/twake/frontend/src/app/atoms/alert/index.tsx b/twake/frontend/src/app/atoms/alert/index.tsx new file mode 100644 index 0000000000..f5ff5b9090 --- /dev/null +++ b/twake/frontend/src/app/atoms/alert/index.tsx @@ -0,0 +1,50 @@ +export const Alert = (props: { + theme: 'success' | 'danger' | 'warning' | 'gray' | 'primary'; + title: string; + icon: any; + className?: string; + bullets?: string[]; + children?: React.ReactNode; +}) => { + let color = 'blue'; + let textColor = 'white'; + if (props.theme === 'success') color = 'green-500'; + if (props.theme === 'danger') color = 'red-500'; + if (props.theme === 'warning') color = 'orange-500'; + if (props.theme === 'gray') { + color = 'zinc-50'; + textColor = 'zinc-900'; + } + if (props.theme === 'primary') { + color = 'blue-100'; + textColor = 'zinc-900'; + } + + return ( +
+
+
+
+
+

{props.title}

+ {(props.bullets || []).length > 0 && ( +
+
    + {(props.bullets || []).map(bullet => ( +
  • {bullet}
  • + ))} +
+
+ )} + {props.children} +
+
+
+ ); +}; diff --git a/twake/frontend/src/app/atoms/avatar/index.stories.tsx b/twake/frontend/src/app/atoms/avatar/index.stories.tsx new file mode 100644 index 0000000000..c8df3f05e8 --- /dev/null +++ b/twake/frontend/src/app/atoms/avatar/index.stories.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { ComponentStory } from '@storybook/react'; +import Avatar from '.'; +import { UserIcon } from '@atoms/icons-agnostic/index'; + +export default { + title: '@atoms/avatar', +}; +type sizeType = 'lg' | 'md' | 'sm'; +type shapeType = 'circle' | 'square'; + +const Template: ComponentStory = (args: { title: string }) => { + const types = ['circle', 'square'] as shapeType[]; + const sizes = ['lg', 'md', 'sm'] as sizeType[]; + const values = [ + { title: args.title }, + { + title: args.title, + avatar: + 'https://images.freeimages.com/images/small-previews/d67/experimenting-with-nature-1547377.jpg', + }, + { + icon: , + className: 'opacity-50', + }, + ]; + + return ( + <> +
+ {sizes.map(size => ( +
+ {types.map(tp => + values.map(val => ( + + )), + )} +
+ ))} +
+ + ); +}; + +export const Default = Template.bind({}); +Default.args = { + title: 'User Name', +}; diff --git a/twake/frontend/src/app/atoms/avatar/index.tsx b/twake/frontend/src/app/atoms/avatar/index.tsx new file mode 100644 index 0000000000..697b862a7d --- /dev/null +++ b/twake/frontend/src/app/atoms/avatar/index.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import _ from 'lodash'; + +// @ts-ignore + +interface AvatarProps extends React.InputHTMLAttributes { + type?: 'circle' | 'square'; + size?: 'lg' | 'md' | 'sm' | 'xs'; + avatar?: string; + icon?: JSX.Element; + title?: string; +} + +const gradients = [ + '#9F2EF4 15.98%, #F97D64 50.17%, #F6C533 82.97%', + '#0099C0 12.87%, #0099C0 49.65%, #3DD5A8 84.94%', + '#D3A6FF 15.1%, #B966B5 50.52%, #7E72C6 85.13%', + '#E2EF54 14.56%, #FF5C66 47.57%, #6248D5 83.84%', + '#FF5CF1 14.48%, #B38ADE 51.66%, #56CDDF 84.61%', + '#75C192 14.48%, #70BDA0 51.66%, #21B59C 84.61%', + '#FFA6AF 14.87%, #E62E40 50.07%, #AA0909 84.36%', + '#335F50 14.87%, #47888C 50.07%, #08C992 84.36%', + '#6CD97E 15.23%, #12B312 56.97%, #117600 84.49%', + '#7DF1FA 14.84%, #2BB4D6 49.93%, #008AA2 82.63%', + '#FFBF80 13.66%, #E66B2E 51.13%, #A64300 84.79%', +]; + +const getGradient = (title = '') => { + let output = 0; + for (let i = 0; i < title.length; i++) { + output += title[i].charCodeAt(0); + } + return gradients[output % 11]; +}; + +const sizes = { lg: 14, md: 11, sm: 9, xs: 6 }; +const fontSizes = { lg: '2xl', md: 'lg', sm: 'md', xs: 'sm' }; + +export default function Avatar(props: AvatarProps) { + const avatarType = props.type || 'circle'; + const avatarSize = sizes[props.size || 'md']; + const fontSize = fontSizes[props.size || 'md']; + const addedClassName = props.className || ''; + const avatarTitle = props.title || ''; + const restProps = _.omit(props, 'size', 'type', 'avatar', 'title', 'className', 'icon'); + + let className = `w-${avatarSize} h-${avatarSize} ${ + avatarType === 'circle' ? 'rounded-full' : 'rounded-sm' + } `; + + if (props.icon) { + className += ' border border-gray-500 '; + return ( +
+ {props.icon} +
+ ); + } + + if (props.avatar) { + return ( +
+ {props.title} +
+ ); + } + + className += ' border border-gray flex items-center justify-center bg-gradient-to-r '; + + const spl_title = avatarTitle.split(' '); + + let letters = avatarTitle.slice(0, 1); + if (spl_title.length > 1) { + letters = spl_title[0].slice(0, 1) + spl_title[1].slice(0, 1); + } + + const lettersClass = `font-medium bg-gray text-white text-${fontSize}`; + + const style = { background: `linear-gradient(135deg, ${getGradient(props.title)})` }; + + return ( +
+
{letters.toUpperCase()}
+
+ ); +} diff --git a/twake/frontend/src/app/atoms/badge/index.stories.tsx b/twake/frontend/src/app/atoms/badge/index.stories.tsx new file mode 100644 index 0000000000..7dd3e807ee --- /dev/null +++ b/twake/frontend/src/app/atoms/badge/index.stories.tsx @@ -0,0 +1,107 @@ +import { ComponentStory } from '@storybook/react'; +import { Badge } from '.'; +import { PlusIcon, SearchIcon } from '@heroicons/react/solid'; +import { TrashIcon } from '@heroicons/react/outline'; + +export default { + title: '@atoms/button', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( + <> + + {props.text} + + + + {props.text} + + + + {props.text} + + + + {props.text} + + + + {props.text} + + +
+ + + Search + + + + Add + + + + +
+ + + {props.text} + + + + {props.text} + + + + {props.text} + + +
+ + + + + + + +
+ + + Add + + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + text: 'Text', + loading: false, +}; diff --git a/twake/frontend/src/app/atoms/badge/index.tsx b/twake/frontend/src/app/atoms/badge/index.tsx new file mode 100644 index 0000000000..7084a4f6fb --- /dev/null +++ b/twake/frontend/src/app/atoms/badge/index.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import _ from 'lodash'; + +interface BadgeProps extends Omit, 'size'> { + theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline'; + size?: 'md' | 'lg' | 'sm'; + icon?: (props: any) => JSX.Element; + loading?: boolean; + children?: React.ReactNode; +} + +export const Badge = (props: BadgeProps) => { + let className = 'text-white bg-blue-500 border-transparent '; + + if (props.theme === 'secondary') className = 'text-blue-500 bg-blue-100 border-transparent '; + + if (props.theme === 'danger') className = 'text-white bg-rose-500 border-transparent '; + + if (props.theme === 'default') + className = 'text-black dark:text-white bg-white dark:bg-zinc-800 border-gray-300'; + + if (props.theme === 'outline') + className = 'text-blue-500 bg-white dark:bg-zinc-800 border-blue-500'; + + if (props.size === 'lg') className = className + ' text-lg h-11'; + else if (props.size === 'sm') className = className + ' text-sm h-7 px-3'; + else className = className + ' text-base h-9'; + + if (!props.children) { + if (props.size === 'lg') className = className + ' w-11 !p-0 justify-center'; + else if (props.size === 'sm') className = className + ' w-7 !p-0 justify-center'; + else className = className + ' w-9 !p-0 justify-center'; + } + + return ( +
+ {props.loading && ( + <> + + + + {' '} + + )} + {props.icon && !(props.loading && !props.children) && ( + + )} + {props.children} +
+ ); +}; diff --git a/twake/frontend/src/app/atoms/button/button.stories.tsx b/twake/frontend/src/app/atoms/button/button.stories.tsx new file mode 100644 index 0000000000..02e55fcfc4 --- /dev/null +++ b/twake/frontend/src/app/atoms/button/button.stories.tsx @@ -0,0 +1,181 @@ +import React from 'react'; +import { ComponentStory } from '@storybook/react'; +import { Button } from './button'; +import { PlusIcon, SearchIcon } from '@heroicons/react/solid'; +import { TrashIcon } from '@heroicons/react/outline'; +import Avatar from '@atoms/avatar'; +import { UserAddIcon } from '@atoms/icons-agnostic/index'; + +export default { + title: '@atoms/button', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( + <> + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + ); +}; + +export const Default = Template.bind({}); +Default.args = { + text: 'Text', + loading: false, + disabled: false, +}; diff --git a/twake/frontend/src/app/atoms/button/button.tsx b/twake/frontend/src/app/atoms/button/button.tsx new file mode 100644 index 0000000000..44f71e80cf --- /dev/null +++ b/twake/frontend/src/app/atoms/button/button.tsx @@ -0,0 +1,97 @@ +import React from 'react'; +import _ from 'lodash'; + +interface ButtonProps extends React.ButtonHTMLAttributes { + theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline' | 'dark'; + size?: 'md' | 'lg' | 'sm'; + icon?: (props: any) => JSX.Element; + iconSize?: 'md' | 'lg'; + loading?: boolean; + disabled?: boolean; + children?: React.ReactNode; +} + +export const Button = (props: ButtonProps) => { + const disabled = props.disabled || props.loading; + + let className = 'text-white bg-blue-500 hover:bg-blue-700 active:bg-blue-800 border-transparent '; + + if (props.theme === 'secondary') + className = + 'text-blue-500 bg-blue-100 hover:bg-blue-200 active:bg-blue-300 border-transparent '; + + if (props.theme === 'danger') + className = 'text-white bg-rose-500 hover:bg-rose-600 active:bg-rose-700 border-transparent '; + + if (props.theme === 'default') + className = + 'text-black dark:text-white bg-white dark:bg-zinc-800 dark:hover:bg-zinc-700 dark:active:bg-zinc-900 hover:bg-gray-50 active:bg-gray-200 border-gray-300'; + + if (props.theme === 'outline') + className = + 'text-blue-500 bg-white dark:bg-zinc-800 dark:hover:bg-zinc-700 dark:active:bg-zinc-900 hover:bg-gray-50 active:bg-gray-200 border-blue-500'; + + if (props.theme === 'dark') + className = + 'text-zinc-300 border-0 bg-zinc-900 hover:bg-zinc-800 hover:text-white active:bg-zinc-900'; + + if (disabled) className += ' opacity-50 pointer-events-none'; + + if (props.size === 'lg') className = className + ' text-lg h-11'; + else if (props.size === 'sm') className = className + ' text-sm h-7 px-3'; + else className = className + ' text-base h-9'; + + if (!props.children) { + if (props.size === 'lg') className = className + ' w-11 !p-0 justify-center'; + else if (props.size === 'sm') className = className + ' w-7 !p-0 justify-center'; + else className = className + ' w-9 !p-0 justify-center'; + } + + return ( + + ); +}; diff --git a/twake/frontend/src/app/atoms/button/confirm.stories.tsx b/twake/frontend/src/app/atoms/button/confirm.stories.tsx new file mode 100644 index 0000000000..f1d5a72167 --- /dev/null +++ b/twake/frontend/src/app/atoms/button/confirm.stories.tsx @@ -0,0 +1,56 @@ +import React from 'react'; +import { ComponentStory } from '@storybook/react'; +import { ButtonConfirm } from './confirm'; +import { RecoilRoot } from 'recoil'; + +export default { + title: '@atoms/button-confirm', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( + + + {props.text} + +
+ + {props.text} + +
+ + {props.text} + +
+ + {props.text} + +
+ ); +}; + +export const Default = Template.bind({}); +Default.args = { + text: 'Text', + loading: false, + disabled: false, +}; diff --git a/twake/frontend/src/app/atoms/button/confirm.tsx b/twake/frontend/src/app/atoms/button/confirm.tsx new file mode 100644 index 0000000000..811f9bac1a --- /dev/null +++ b/twake/frontend/src/app/atoms/button/confirm.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { ExclamationCircleIcon } from '@heroicons/react/outline'; +import _ from 'lodash'; +import { useState } from 'react'; +import { Button } from './button'; +import { Modal, ModalContent } from '../modal'; + +interface ButtonProps extends React.ButtonHTMLAttributes { + theme?: 'primary' | 'secondary' | 'danger' | 'default' | 'outline'; + size?: 'md' | 'lg' | 'sm'; + icon?: (props: any) => JSX.Element; + loading?: boolean; + disabled?: boolean; + confirmTitle?: string; + confirmMessage?: string; + confirmIcon?: React.ReactNode; + confirmButtonTheme?: 'primary' | 'secondary' | 'danger' | 'default'; + confirmButtonText?: string; + cancelButtonText?: string; + children?: React.ReactNode; +} + +export const ButtonConfirm = (props: ButtonProps) => { + const [inConfirm, setInConfirm] = useState(false); + return ( + <> + + + + } + /> + + + ); +}; diff --git a/twake/frontend/src/app/atoms/colors/index.stories.tsx b/twake/frontend/src/app/atoms/colors/index.stories.tsx new file mode 100644 index 0000000000..130374451c --- /dev/null +++ b/twake/frontend/src/app/atoms/colors/index.stories.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { ComponentStory } from '@storybook/react'; + +export default { + title: '@atoms/colors', +}; + +const Template: ComponentStory = () => { + return ( + <> +
+ {['zink', 'red', 'orange', 'green', 'blue'].map(color => ( +
+
+
+
+
+ {color} +
+
+
+
+ {[50, 100, 200, 300, 400, 500, 600, 700, 800, 900].map(shade => ( +
+
+
+
+ {shade} +
+
+ #... +
+
+
+ ))} +
+
+
+ ))} +
+ + ); +}; + +export const Default = Template.bind({}); +Default.args = {}; diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/check.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/check.svg new file mode 100644 index 0000000000..69e9bfd4f2 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/check.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/copy.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/copy.svg new file mode 100644 index 0000000000..29ca723bd1 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/delete.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/delete.svg new file mode 100644 index 0000000000..a508bd5099 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/delete.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/download.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/download.svg new file mode 100644 index 0000000000..452d1edcab --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/download.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/eye.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/eye.svg new file mode 100644 index 0000000000..c19b8afc2e --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/eye.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/input-clear.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/input-clear.svg new file mode 100644 index 0000000000..95b3dd513b --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/input-clear.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/plus.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/plus.svg new file mode 100644 index 0000000000..d0c661becb --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/rotate-cw.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/rotate-cw.svg new file mode 100644 index 0000000000..923d226c52 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/rotate-cw.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/share.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/share.svg new file mode 100644 index 0000000000..1de8c4a95e --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/share.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check-double.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check-double.svg new file mode 100644 index 0000000000..06adcf306c --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check-double.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check.svg new file mode 100644 index 0000000000..34dc0e5e21 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/status-check.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/up.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/up.svg new file mode 100644 index 0000000000..205b0645fd --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/up.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/upload.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/upload.svg new file mode 100644 index 0000000000..be06382d10 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/upload.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/user-add.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/user-add.svg new file mode 100644 index 0000000000..49305f3382 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/user-add.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/vertical-dots.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/vertical-dots.svg new file mode 100644 index 0000000000..3cd84b75a1 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/vertical-dots.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/x.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/x.svg new file mode 100644 index 0000000000..6eaebcca33 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/x.svg @@ -0,0 +1,3 @@ + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-in.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-in.svg new file mode 100644 index 0000000000..3a6104dae9 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-in.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-out.svg b/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-out.svg new file mode 100644 index 0000000000..96b455f9c5 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/assets/zoom-out.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-agnostic/icons-agnostic.stories.tsx b/twake/frontend/src/app/atoms/icons-agnostic/icons-agnostic.stories.tsx new file mode 100644 index 0000000000..741340a903 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/icons-agnostic.stories.tsx @@ -0,0 +1,74 @@ +import React, { cloneElement, ComponentProps } from 'react'; +import { ComponentStory } from '@storybook/react'; +import { + CopyIcon, + DeleteIcon, + DownloadIcon, + EyeIcon, + InputClearIcon, + ShareIcon, + UserAddIcon, + CheckIcon, + ZoomInIcon, + ZoomOutIcon, + VerticalDotsIcon, + RotateCwIcon, + UploadCwIcon, + PlusIcon, + UpIcon, + XIcon, + StatusCheckDoubleIcon, + StatusCheckIcon, +} from '@atoms/icons-agnostic/index'; + +export default { + title: '@atoms/icons-agnostic', +}; + +type PropsType = { + icon: JSX.Element; + title: string; +}; + +const Icon = ({ icon, title }: PropsType): JSX.Element => { + const comp = cloneElement(icon, { className: 'w-8 h-8' }); + + return ( +
+ {comp} +
{title}
+
+ ); +}; + +// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const Template: ComponentStory = (props: ComponentProps<'svg'>) => { + return ( + <> +
+ } title="Copy" /> + } title="Delete" /> + } title="Download" /> + } title="Eye" /> + } title="Share" /> + } title="InputClear" /> + } title="User" /> + } title="Check" /> + } title="ZoomIn" /> + } title="ZoomOut" /> + } title="VerticalDots" /> + } title="RotateCw" /> + } title="Upload" /> + } title="Plus" /> + } title="Up" /> + } title="X" /> + } title="StatusCheckDouble" /> + } title="StatusCheck" /> +
+ + ); +}; + +export const Default = Template.bind({}); +// More on args: https://storybook.js.org/docs/react/writing-stories/args +Default.args = {}; diff --git a/twake/frontend/src/app/atoms/icons-agnostic/index.tsx b/twake/frontend/src/app/atoms/icons-agnostic/index.tsx new file mode 100644 index 0000000000..6563b760fa --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-agnostic/index.tsx @@ -0,0 +1,41 @@ +import React, { ComponentProps } from 'react'; + +import { ReactComponent as CopySvg } from './assets/copy.svg'; +import { ReactComponent as DeleteSvg } from './assets/delete.svg'; +import { ReactComponent as DownloadSvg } from './assets/download.svg'; +import { ReactComponent as UploadSvg } from './assets/upload.svg'; +import { ReactComponent as InputClearSvg } from './assets/input-clear.svg'; +import { ReactComponent as ShareSvg } from './assets/share.svg'; +import { ReactComponent as EyeSvg } from './assets/eye.svg'; +import { ReactComponent as UserAddSvg } from './assets/user-add.svg'; +import { ReactComponent as CheckSvg } from './assets/check.svg'; +import { ReactComponent as ZommInSvg } from './assets/zoom-in.svg'; +import { ReactComponent as ZoomOutSvg } from './assets/zoom-out.svg'; +import { ReactComponent as VerticalDotsSvg } from './assets/vertical-dots.svg'; +import { ReactComponent as RotateCwSvg } from './assets/rotate-cw.svg'; +import { ReactComponent as Plus } from './assets/plus.svg'; +import { ReactComponent as Up } from './assets/up.svg'; +import { ReactComponent as X } from './assets/x.svg'; +import { ReactComponent as StatusCheckDouble } from './assets/status-check-double.svg'; +import { ReactComponent as StatusCheck } from './assets/status-check.svg'; + +export const CopyIcon = (props: ComponentProps<'svg'>) => ; +export const DeleteIcon = (props: ComponentProps<'svg'>) => ; +export const DownloadIcon = (props: ComponentProps<'svg'>) => ; +export const EyeIcon = (props: ComponentProps<'svg'>) => ; +export const InputClearIcon = (props: ComponentProps<'svg'>) => ; +export const ShareIcon = (props: ComponentProps<'svg'>) => ; +export const UserAddIcon = (props: ComponentProps<'svg'>) => ; +export const CheckIcon = (props: ComponentProps<'svg'>) => ; +export const ZoomInIcon = (props: ComponentProps<'svg'>) => ; +export const ZoomOutIcon = (props: ComponentProps<'svg'>) => ; +export const VerticalDotsIcon = (props: ComponentProps<'svg'>) => ; +export const RotateCwIcon = (props: ComponentProps<'svg'>) => ; +export const UploadCwIcon = (props: ComponentProps<'svg'>) => ; +export const PlusIcon = (props: ComponentProps<'svg'>) => ; +export const UpIcon = (props: ComponentProps<'svg'>) => ; +export const XIcon = (props: ComponentProps<'svg'>) => ; +export const StatusCheckDoubleIcon = (props: ComponentProps<'svg'>) => ( + +); +export const StatusCheckIcon = (props: ComponentProps<'svg'>) => ; diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/dismiss.svg b/twake/frontend/src/app/atoms/icons-colored/assets/dismiss.svg new file mode 100644 index 0000000000..c68dff3af6 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/dismiss.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/file-type-archive.svg b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-archive.svg new file mode 100644 index 0000000000..edd6a28a39 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-archive.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/file-type-document.svg b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-document.svg new file mode 100644 index 0000000000..5822334871 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-document.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/file-type-pdf.svg b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-pdf.svg new file mode 100644 index 0000000000..ab9c6ee1eb --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-pdf.svg @@ -0,0 +1,27 @@ + + + + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/file-type-spreadsheet.svg b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-spreadsheet.svg new file mode 100644 index 0000000000..d538ec04fe --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-spreadsheet.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/file-type-unknown.svg b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-unknown.svg new file mode 100644 index 0000000000..0a680b6dbd --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/file-type-unknown.svg @@ -0,0 +1,4 @@ + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/assets/not-found.svg b/twake/frontend/src/app/atoms/icons-colored/assets/not-found.svg new file mode 100644 index 0000000000..e22a154b38 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/assets/not-found.svg @@ -0,0 +1,229 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/twake/frontend/src/app/atoms/icons-colored/icons-colored.stories.tsx b/twake/frontend/src/app/atoms/icons-colored/icons-colored.stories.tsx new file mode 100644 index 0000000000..3c6c3c9767 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/icons-colored.stories.tsx @@ -0,0 +1,59 @@ +import React, { cloneElement, ComponentProps } from 'react'; +import { ComponentStory } from '@storybook/react'; +import { + DismissIcon, + FileTypeArchiveIcon, + FileTypeDocumentIcon, + FileTypePdfIcon, + FileTypeSpreadsheetIcon, + FileTypeUnknownIcon, + NotFoundIcon, +} from '@atoms/icons-colored/index'; + +export default { + title: '@atoms/icons-colored', +}; + +type PropsType = { + icon: JSX.Element; + title: string; +}; + +const Icon = ({ icon, title }: PropsType): JSX.Element => { + const comp = cloneElement(icon, { className: 'w-8 h-8' }); + + return ( +
+ {comp} +
{title}
+
+ ); +}; + +// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const Template: ComponentStory = (props: ComponentProps<'svg'>) => { + return ( + <> +

General

+
+ } title="Dismiss" /> +
+

FileTypes

+
+ } title="FileTypeArchive" /> + } title="FileTypePdf" /> + } title="FileTypeDocument" /> + } title="FileTypeSpreadsheet" /> + } title="FileTypeUnknown" /> +
+

Component specific

+
+ } title="NotFound" /> +
+ + ); +}; + +export const Default = Template.bind({}); +// More on args: https://storybook.js.org/docs/react/writing-stories/args +Default.args = {}; diff --git a/twake/frontend/src/app/atoms/icons-colored/index.tsx b/twake/frontend/src/app/atoms/icons-colored/index.tsx new file mode 100644 index 0000000000..dfab6aaa37 --- /dev/null +++ b/twake/frontend/src/app/atoms/icons-colored/index.tsx @@ -0,0 +1,25 @@ +import React, { ComponentProps } from 'react'; + +import { ReactComponent as DismissSvg } from './assets/dismiss.svg'; +import { ReactComponent as NotFoundSvg } from './assets/not-found.svg'; +import { ReactComponent as FileTypeArchiveSvg } from './assets/file-type-archive.svg'; +import { ReactComponent as FileTypeDocumentSvg } from './assets/file-type-document.svg'; +import { ReactComponent as FileTypePdfSvg } from './assets/file-type-pdf.svg'; +import { ReactComponent as FileTypeSpreadsheetSvg } from './assets/file-type-spreadsheet.svg'; +import { ReactComponent as FileTypeUnknownSvg } from './assets/file-type-unknown.svg'; + +export const DismissIcon = (props: ComponentProps<'svg'>) => ; +export const NotFoundIcon = (props: ComponentProps<'svg'>) => ; +export const FileTypeArchiveIcon = (props: ComponentProps<'svg'>) => ( + +); +export const FileTypePdfIcon = (props: ComponentProps<'svg'>) => ; +export const FileTypeDocumentIcon = (props: ComponentProps<'svg'>) => ( + +); +export const FileTypeSpreadsheetIcon = (props: ComponentProps<'svg'>) => ( + +); +export const FileTypeUnknownIcon = (props: ComponentProps<'svg'>) => ( + +); diff --git a/twake/frontend/src/app/atoms/input/input-decoration-icon.tsx b/twake/frontend/src/app/atoms/input/input-decoration-icon.tsx new file mode 100644 index 0000000000..66fa6aa0ba --- /dev/null +++ b/twake/frontend/src/app/atoms/input/input-decoration-icon.tsx @@ -0,0 +1,22 @@ +import { ReactNode } from 'react'; + +interface InputLabelProps { + prefix?: (props: any) => JSX.Element; + suffix?: (props: any) => JSX.Element; + input: ({ className }: { className: string }) => ReactNode; + className?: string; +} + +export const InputDecorationIcon = (props: InputLabelProps) => { + return ( +
+ {props.prefix && ( + + )} + {props.input({ className: (props.prefix ? 'pl-9 ' : '') + (props.suffix ? 'pr-9 ' : '') })} + {props.suffix && ( + + )} +
+ ); +}; diff --git a/twake/frontend/src/app/atoms/input/input-decoration-label.tsx b/twake/frontend/src/app/atoms/input/input-decoration-label.tsx new file mode 100644 index 0000000000..4a998e8b59 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/input-decoration-label.tsx @@ -0,0 +1,28 @@ +import _ from 'lodash'; +import { Info } from '../text'; + +interface InputLabelProps { + label?: string; + feedback?: string; + hasError?: boolean; + input?: React.ReactNode; + className?: string; +} + +export const InputLabel = (props: InputLabelProps) => { + return ( + <> + {props.label && ( +
+ +
{props.input}
+ {props.feedback && ( + + {props.feedback} + + )} +
+ )} + + ); +}; diff --git a/twake/frontend/src/app/atoms/input/input-select.tsx b/twake/frontend/src/app/atoms/input/input-select.tsx new file mode 100644 index 0000000000..971e90c286 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/input-select.tsx @@ -0,0 +1,32 @@ +import _ from 'lodash'; +import { defaultInputClassName, errorInputClassName } from './input-text'; + +interface InputProps extends Omit, 'size'> { + theme?: 'plain' | 'outline'; + hasError?: boolean; + size?: 'md' | 'lg' | 'sm'; + className?: string; + children?: React.ReactNode; +} + +export function Select(props: InputProps) { + let inputClassName = props.hasError + ? errorInputClassName(props.theme) + : defaultInputClassName(props.theme); + inputClassName = inputClassName + (props.disabled ? ' opacity-75' : ''); + + if (props.size === 'lg') inputClassName = inputClassName + ' text-lg h-11'; + else if (props.size === 'sm') inputClassName = inputClassName + ' text-sm h-7 py-0 px-3'; + else inputClassName = inputClassName + ' text-base h-9 py-1'; + + return ( + + ); +} + +export default Select; diff --git a/twake/frontend/src/app/atoms/input/input-text.tsx b/twake/frontend/src/app/atoms/input/input-text.tsx new file mode 100644 index 0000000000..ed23081a43 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/input-text.tsx @@ -0,0 +1,75 @@ +import _ from 'lodash'; +import React from 'react'; + +interface InputProps + extends Omit< + React.InputHTMLAttributes & React.TextareaHTMLAttributes, + 'size' + > { + theme?: 'plain' | 'outline'; + label?: string; + size?: 'sm' | 'md' | 'lg'; + feedback?: string; + hasError?: boolean; + multiline?: boolean; + inputComponent?: React.ReactNode; + inputClassName?: string; + className?: string; + inputRef?: React.Ref; +} + +const baseInputClassName = + 'tw-input block w-full rounded-md focus:ring-1 focus:ring-blue-500 z-0 focus:z-10 dark:text-white text-black '; + +export const defaultInputClassName = (theme: 'plain' | 'outline' = 'plain') => { + return ( + baseInputClassName + + (theme === 'plain' + ? 'bg-zinc-200 border-zinc-200 dark:bg-zinc-800 dark:border-zinc-800' + : 'bg-zinc-50 border-zinc-300 dark:bg-zinc-800 dark:border-zinc-700') + ); +}; + +export const errorInputClassName = (theme: 'plain' | 'outline' = 'plain') => { + return ( + baseInputClassName + + (theme === 'plain' + ? 'bg-red-200 border-red-200 dark:bg-red-800 dark:border-red-800' + : 'bg-red-50 border-red-300 dark:bg-red-900 dark:border-red-800') + ); +}; + +export const Input = (props: InputProps) => { + let inputClassName = props.hasError + ? errorInputClassName(props.theme) + : defaultInputClassName(props.theme); + inputClassName = inputClassName + (props.disabled ? ' opacity-75' : ''); + + if (!props.multiline) { + if (props.size === 'lg') inputClassName = inputClassName + ' h-11'; + else if (props.size === 'sm') inputClassName = inputClassName + ' h-7'; + else inputClassName = inputClassName + ' h-9'; + } + + return ( + <> + {props.inputComponent || + (props.multiline ? ( + + ) : ( + } + type="text" + className={inputClassName + ' ' + props.inputClassName + ' ' + props.className} + {..._.omit(props, 'label', 'inputClassName', 'className', 'size')} + /> + ))} + + ); +}; diff --git a/twake/frontend/src/app/atoms/input/stories/input-groups.stories.tsx b/twake/frontend/src/app/atoms/input/stories/input-groups.stories.tsx new file mode 100644 index 0000000000..dcad901c79 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/stories/input-groups.stories.tsx @@ -0,0 +1,110 @@ +import { ComponentStory } from '@storybook/react'; +import { SearchIcon } from '@heroicons/react/solid'; +import { Title } from '@atoms/text'; +import { Input } from '../input-text'; +import { FilterIcon, CogIcon } from '@heroicons/react/outline'; +import Select from '../input-select'; +import { InputDecorationIcon } from '../input-decoration-icon'; + +export default { + title: '@atoms/input-groups', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( + <> + Icons +
+ + } + /> +
+ + } + /> +
+ + } + /> +
+ + ( + + )} + /> +
+ + ( + + )} + /> + +
+
+ Groups +
+ +
+ + +
+ +
+
+ Mixed +
+ +
+ ( + + )} + /> + ( + + )} + /> +
+ + ); +}; + +export const Default = Template.bind({}); +Default.args = { + text: 'Text', + disabled: false, +}; diff --git a/twake/frontend/src/app/atoms/input/stories/input.stories.tsx b/twake/frontend/src/app/atoms/input/stories/input.stories.tsx new file mode 100644 index 0000000000..afb0ba8961 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/stories/input.stories.tsx @@ -0,0 +1,72 @@ +import { ComponentStory } from '@storybook/react'; +import { Input } from '../input-text'; +import { Title } from '../../text'; +import { InputLabel } from '../input-decoration-label'; + +export default { + title: '@atoms/input', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( +
+ Sizes and themes plain / outline +
+ + +
+ +
+ +
+ + +
+ +
+ +
+ Labels and errors +
+ + +
+ + } + /> +
+ + } + /> +
+ ); +}; + +export const Default = Template.bind({}); +Default.args = { + text: 'Text', + disabled: false, +}; diff --git a/twake/frontend/src/app/atoms/input/stories/select.stories.tsx b/twake/frontend/src/app/atoms/input/stories/select.stories.tsx new file mode 100644 index 0000000000..b3ad371871 --- /dev/null +++ b/twake/frontend/src/app/atoms/input/stories/select.stories.tsx @@ -0,0 +1,57 @@ +import { ComponentStory } from '@storybook/react'; +import { Title } from '@atoms/text'; +import { InputLabel } from '../input-decoration-label'; +import Select from '../input-select'; + +export default { + title: '@atoms/select', +}; + +const Template: ComponentStory = (props: { + text: string; + disabled: boolean; + loading: boolean; +}) => { + return ( +
+ Sizes and with error +
+ + +
+ +
+ +
+ + Labels +
+ + + + + + } + /> +
+ ); +}; + +export const Default = Template.bind({}); +Default.args = { + disabled: false, +}; diff --git a/twake/frontend/src/app/atoms/layout/single-center-card.tsx b/twake/frontend/src/app/atoms/layout/single-center-card.tsx new file mode 100644 index 0000000000..47299be5eb --- /dev/null +++ b/twake/frontend/src/app/atoms/layout/single-center-card.tsx @@ -0,0 +1,48 @@ +export default function SingleCenterCard(props: { + logo?: boolean; + insetLogo?: boolean; + title?: string | React.ReactNode; + subtitle?: string | React.ReactNode; + children: React.ReactNode; +}) { + return ( +
+ {(!!props.logo || !!props.title || !!props.subtitle) && ( +
+ Workflow + {!!props.title && ( +

+ {props.title} +

+ )} + {!!props.subtitle && ( +

+ {props.subtitle} +

+ )} +
+ )} + +
+
+ {props.insetLogo && ( + Workflow + )} + + {props.children} +
+
+
+ ); +} diff --git a/twake/frontend/src/app/atoms/link/index.tsx b/twake/frontend/src/app/atoms/link/index.tsx new file mode 100644 index 0000000000..fee0bceb32 --- /dev/null +++ b/twake/frontend/src/app/atoms/link/index.tsx @@ -0,0 +1,35 @@ +import _ from 'lodash'; +import { Link } from 'react-router-dom'; + +export default function A( + props: any & { + to?: string; + href?: string; + children: React.ReactNode; + noColor?: boolean; + }, +) { + const colors = props.noColor ? '' : 'hover:text-blue-700 active:text-blue-800 text-blue-500'; + + if (props.to) { + return ( + + {props.children} + + ); + } + + return ( + + {props.children} + + ); +} diff --git a/twake/frontend/src/app/atoms/link/link.stories.tsx b/twake/frontend/src/app/atoms/link/link.stories.tsx new file mode 100644 index 0000000000..f5e1d1516f --- /dev/null +++ b/twake/frontend/src/app/atoms/link/link.stories.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import A from './index'; + +export default { + title: '@atoms/link', + component: A, + decorators: [(Story) => ()] +} as ComponentMeta; + +const Template: ComponentStory = args => ; + +export const Default = Template.bind({}); +Default.args = { + href: 'https://www.google.com', + children: 'Link', +} + +export const noColor = Template.bind({}); +noColor.args = { + href: 'https://www.google.com', + children: 'Link', + noColor: true, +}; + +export const internal = Template.bind({}); +internal.args = { + to: '/', + children: 'Link', +}; diff --git a/twake/frontend/src/app/atoms/loader/index.tsx b/twake/frontend/src/app/atoms/loader/index.tsx new file mode 100644 index 0000000000..a2692306f7 --- /dev/null +++ b/twake/frontend/src/app/atoms/loader/index.tsx @@ -0,0 +1,24 @@ +export const Loader = (props: { className?: string }) => { + return ( + + + + + ); +}; diff --git a/twake/frontend/src/app/atoms/logo/index.tsx b/twake/frontend/src/app/atoms/logo/index.tsx new file mode 100644 index 0000000000..cc1086f8c7 --- /dev/null +++ b/twake/frontend/src/app/atoms/logo/index.tsx @@ -0,0 +1,23 @@ +import _ from 'lodash'; +import React from 'react'; + +interface PropsType extends Omit, 'size'> { + size?: 16 | 32 | 64 | 128 | 256; +} + +export const Logo = (props: PropsType): React.ReactElement => { + const { size = 128 } = props; + + return ( +
+ Twake logo +
+ ); +}; diff --git a/twake/frontend/src/app/atoms/logo/logo.stories.tsx b/twake/frontend/src/app/atoms/logo/logo.stories.tsx new file mode 100644 index 0000000000..83ad70b9b0 --- /dev/null +++ b/twake/frontend/src/app/atoms/logo/logo.stories.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { Logo } from '.'; + +export default { + title: '@atoms/logo', + component: Logo, +} as ComponentMeta; + +const Template: ComponentStory = args => ; + +export const Default = Template.bind({}); +Default.args = {}; + +export const extraSmall = Template.bind({}); +extraSmall.args = { + size: 16, +}; + +export const small = Template.bind({}); +small.args = { + size: 32, +}; + +export const mediumSmall = Template.bind({}); +mediumSmall.args = { + size: 64, +}; + +export const medium = Template.bind({}); +medium.args = { + size: 128, +}; + +export const large = Template.bind({}); +large.args = { + size: 256, +}; diff --git a/twake/frontend/src/app/atoms/modal/index.stories.tsx b/twake/frontend/src/app/atoms/modal/index.stories.tsx new file mode 100644 index 0000000000..7594b34299 --- /dev/null +++ b/twake/frontend/src/app/atoms/modal/index.stories.tsx @@ -0,0 +1,93 @@ +import React, { useState } from 'react'; +import { RecoilRoot } from 'recoil'; +import { ComponentStory } from '@storybook/react'; +import { Modal, ModalContent } from '.'; +import { Button } from '../button/button'; +import { ButtonConfirm } from '../button/confirm'; +import { CheckCircleIcon, ExclamationCircleIcon } from '@heroicons/react/outline'; +import { Title } from '../text'; +import { Dialog } from '@headlessui/react'; + +export default { + title: '@atoms/modal', +}; + +const Template: ComponentStory = (props: {}) => { + const [openA, setOpenA] = useState(false); + const [openB, setOpenB] = useState(false); + + return ( + + setOpenB(false)}> + Title + Hello this is the modal B
+ No more popup now +
+ setOpenA(false)}> + Title + Hello this is the modal A
+ setOpenB(true)}>Open B +
+ +
+ ); +}; + +export const Default = Template.bind({}); +Default.args = {}; + +const TemplateWithContent: ComponentStory = (props: {}) => { + const [openA, setOpenA] = useState(false); + const [openB, setOpenB] = useState(false); + + return ( + + setOpenB(false)}> + + + + + } + /> + + setOpenA(false)}> + + setOpenB(true)}>Open modal B + + } + /> + + + + ); +}; + +export const WithModalContent = TemplateWithContent.bind({}); +WithModalContent.args = {}; diff --git a/twake/frontend/src/app/atoms/modal/index.tsx b/twake/frontend/src/app/atoms/modal/index.tsx new file mode 100644 index 0000000000..631ce4b770 --- /dev/null +++ b/twake/frontend/src/app/atoms/modal/index.tsx @@ -0,0 +1,196 @@ +import { Dialog, Transition } from '@headlessui/react'; +import { Fragment, ReactNode, useCallback, useEffect, useState } from 'react'; +import { atom, useRecoilState } from 'recoil'; +import { DismissIcon } from '../icons-colored'; +import { Title } from '../text'; + +const ModalsCountState = atom({ + key: 'ModalsState', + default: 0, +}); + +let visibleModals = 0; + +export const Modal = (props: { + open?: boolean; + onClose?: () => void; + children?: React.ReactNode; + closable?: boolean; + className?: string; + style?: React.CSSProperties; + positioned?: boolean; +}) => { + const [open, setOpen] = useState(false); + const [, setModalsCountState] = useRecoilState(ModalsCountState); + const [level, setLevel] = useState(0); + const [didOpenOnce, setDidOpenOnce] = useState(false); + + const onClose = useCallback(() => { + visibleModals += -1; + setModalsCountState(visibleModals); + }, [setModalsCountState]); + + const onOpen = useCallback(() => { + visibleModals += 1; + setLevel(visibleModals); + setModalsCountState(visibleModals); + }, [setModalsCountState]); + + useEffect(() => { + if (props.open !== open) { + setOpen(props.open || false); + if (props.open) { + onOpen(); + } else { + onClose(); + } + } + if (!didOpenOnce && props.open) setDidOpenOnce(true); + }, [props.open]); + + useEffect(() => { + return () => { + if (open) onClose(); + }; + }, []); + + const zIndex = 'z-' + level + '0'; + + return ( + + props.onClose && props.closable && props.onClose()} + > + +
+ + +
+
+ { + /* This element is to trick the browser into centering the modal contents. */ + !props.positioned && ( + + ) + } + + + {props.closable !== false && ( +
+ +
+ )} + {didOpenOnce && props.children} +
+
+
+
+
+
+ ); +}; + +export const ModalContent = (props: { + title: string; + text?: string; + textCenter?: boolean; + buttons?: ReactNode; + children?: ReactNode; + icon?: any; + theme?: 'success' | 'danger' | 'warning' | 'gray'; +}) => { + let color = 'blue'; + if (props.theme === 'success') color = 'green'; + if (props.theme === 'danger') color = 'red'; + if (props.theme === 'warning') color = 'orange'; + if (props.theme === 'gray') color = 'gray'; + return ( + <> +
+ {props.icon && ( +
+
+ )} +
+ {props.title} +
+

{props.text || ''}

+
+
+
+ {props.buttons && ( +
+ {props.buttons} +
+ )} + {props.children} + + ); +}; diff --git a/twake/frontend/src/app/atoms/text/index.stories.tsx b/twake/frontend/src/app/atoms/text/index.stories.tsx new file mode 100644 index 0000000000..e0d16267b9 --- /dev/null +++ b/twake/frontend/src/app/atoms/text/index.stories.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { ComponentStory } from '@storybook/react'; + +import * as Text from '.'; + +export default { + title: '@atoms/text', +}; + +// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args +const Template: ComponentStory = (props: { text: string }) => ( + <> + {props.text || 'Title'} +
+ {props.text || 'Subtitle'} +
+ {props.text || 'Base'} +
+ {props.text || 'BaseSmall'} +
+ {props.text || 'Info'} +
+ {props.text || 'InfoSmall'} +
+ +); + +export const Default = Template.bind({}); +Default.args = { + text: '', +}; diff --git a/twake/frontend/src/app/atoms/text/index.tsx b/twake/frontend/src/app/atoms/text/index.tsx new file mode 100644 index 0000000000..6f71c559fc --- /dev/null +++ b/twake/frontend/src/app/atoms/text/index.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import _ from 'lodash'; +import { ReactNode } from 'react'; + +type TextProps = { + type: 'title' | 'subtitle' | 'base' | 'base-small' | 'info' | 'info-small'; + children: ReactNode | ReactNode[]; + className?: string; + noColor?: boolean; +} & Omit< + React.ButtonHTMLAttributes, + 'children' | 'className' | 'type' | 'noColor' +>; + +type TypedTextProps = Omit; + +export const Title = (props: TypedTextProps) => Text({ type: 'title', ...props }); + +export const Subtitle = (props: TypedTextProps) => Text({ type: 'subtitle', ...props }); + +export const Base = (props: TypedTextProps) => Text({ type: 'base', ...props }); + +export const BaseSmall = (props: TypedTextProps) => Text({ type: 'base-small', ...props }); + +export const Info = (props: TypedTextProps) => Text({ type: 'info', ...props }); + +export const InfoSmall = (props: TypedTextProps) => Text({ type: 'info-small', ...props }); + +const Text = (props: TextProps) => { + let defaultClassName = ''; + + switch (props.type) { + case 'title': + defaultClassName = + 'text-lg font-semibold block ' + + ' ' + + (props.noColor ? '' : 'text-zinc-900 dark:text-white'); + break; + case 'subtitle': + defaultClassName = + 'text-base font-semibold' + ' ' + (props.noColor ? '' : 'text-zinc-800 dark:text-white'); + break; + case 'base': + defaultClassName = + 'text-base font-normal' + ' ' + (props.noColor ? '' : 'text-zinc-800 dark:text-white'); + break; + case 'base-small': + defaultClassName = + 'text-sm font-normal' + ' ' + (props.noColor ? '' : 'text-zinc-800 dark:text-white'); + break; + case 'info': + defaultClassName = + 'text-sm font-normal' + + ' ' + + (props.noColor ? '' : 'text-zinc-400 dark:text-white dark:opacity-50'); + break; + case 'info-small': + defaultClassName = + 'text-xs font-normal' + + ' ' + + (props.noColor ? '' : 'text-zinc-400 dark:text-white dark:opacity-50'); + break; + } + + return ( + + {props.children} + + ); +}; + +export default Text; diff --git a/twake/frontend/src/app/components/AddUserButton/AddUserButton.tsx b/twake/frontend/src/app/components/AddUserButton/AddUserButton.tsx deleted file mode 100644 index 55d1b8d084..0000000000 --- a/twake/frontend/src/app/components/AddUserButton/AddUserButton.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import Icon from 'components/Icon/Icon.js'; -import Languages from 'services/languages/languages'; -import './AddUserButton.scss'; -import popupManager from 'services/popupManager/popupManager.js'; -import AddUserByEmail from 'app/scenes/Client/Popup/AddUser/AddUserByEmail'; - -export default (props: any) => { - return ( -
{ - return popupManager.open(); - }} - > -
-
- -
-
-
- {Languages.t( - 'scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button', - [], - 'Ajouter des collaborateurs', - )} -
-
- ); -}; diff --git a/twake/frontend/src/app/components/AttachmentPicker/AttachmentPicker.js b/twake/frontend/src/app/components/AttachmentPicker/AttachmentPicker.js deleted file mode 100755 index e957c7ffe7..0000000000 --- a/twake/frontend/src/app/components/AttachmentPicker/AttachmentPicker.js +++ /dev/null @@ -1,198 +0,0 @@ -import React, { Component } from 'react'; - -import File from 'components/Drive/File'; -import FilePicker from 'components/Drive/FilePicker/FilePicker.js'; -import TaskPicker from 'components/TaskPicker/TaskPicker.js'; -import Menu from 'components/Menus/Menu.js'; -import Icon from 'components/Icon/Icon.js'; -import Button from 'components/Buttons/Button.js'; -import UploadZone from 'components/Uploads/UploadZone'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Languages from 'services/languages/languages'; -import './AttachmentPicker.scss'; - -export default class AttachmentPicker extends Component { - /* - props : { - readOnly : bool - attachments : [] - onChange - className - } - */ - - getIcon(att) { - if (att.type.toLocaleLowerCase() === 'event') { - return 'calendar-alt'; - } - if (att.type.toLocaleLowerCase() === 'file') { - return 'folder'; - } - if (att.type.toLocaleLowerCase() === 'task') { - return 'check-square'; - } - } - addAttachment(attachment) { - var attachments = this.props.attachments || []; - attachments.push(attachment); - if (this.props.onChange) { - this.props.onChange(attachments); - } - } - removeAttachment(attachment) { - var attachments = this.props.attachments || []; - var index = attachments.indexOf(attachment); - if (index >= 0) { - attachments.splice(index, 1); - if (this.props.onChange) { - this.props.onChange(attachments); - } - } - } - render() { - return ( -
-
- {(Object.values(this.props.attachments || {}) || []).map(att => { - if (att.type === 'file') { - var additionalMenu = []; - if (!this.props.readOnly) { - additionalMenu = [ - { - type: 'menu', - text: Languages.t( - 'components.attachmentpicker.remove_attach', - [], - 'Remove attachment', - ), - onClick: () => { - this.removeAttachment(att); - }, - }, - ]; - } - return ( -
- -
- ); - } - return ( -
- - {att.name} - {!this.props.readOnly && ( - { - this.removeAttachment(att); - }} - /> - )} -
- ); - })} -
- {!this.props.readOnly && ( - { - this.upload_zone.open(); - MenusManager.closeMenu(); - }, - }, - { - type: 'menu', - icon: 'folder', - text: Languages.t( - 'components.attachmentpicker.from_twake', - [], - 'From Twake Documents', - ), - submenu: [ - { - type: 'react-element', - reactElement: ( - { - this.addAttachment({ type: 'file', id: res.id, name: res.name }); - MenusManager.closeMenu(); - }} - initialDirectory={{ id: '' }} - /> - ), - }, - ], - }, - ], - }, - { - type: 'menu', - text: Languages.t('scenes.apps.tasks.task', [], 'Task'), - icon: 'check-square', - submenu: [ - { - type: 'react-element', - reactElement: ( - { - this.addAttachment({ type: 'task', id: res.id, name: res.title }); - MenusManager.closeMenu(); - }} - /> - ), - }, - ], - }, - ]} - > - {' '} - - - )} - - (this.upload_zone = node)} - disableClick - parent={''} - driveCollectionKey={'attachment_' + Workspaces.currentWorkspaceId} - uploadOptions={{ workspace_id: Workspaces.currentWorkspaceId, detached: true }} - onUploaded={res => { - this.addAttachment({ type: 'file', id: res.id, name: res.name }); - }} - multiple={false} - /> -
- ); - } -} diff --git a/twake/frontend/src/app/components/AutoComplete/AutoComplete.tsx b/twake/frontend/src/app/components/AutoComplete/AutoComplete.tsx deleted file mode 100644 index ad9cef1f06..0000000000 --- a/twake/frontend/src/app/components/AutoComplete/AutoComplete.tsx +++ /dev/null @@ -1,399 +0,0 @@ -import React, { Component } from 'react'; -import AutoHeight from '../AutoHeight/AutoHeight'; -import Input from '../Inputs/Input'; -import './AutoComplete.scss'; - -type State = { - currentList: any[]; - selected: number; - resultPosition: string; - selectedUser: object; - focused: any; -}; - -type Props = { - onResize?: any; - autoHeight?: any; - className?: string; - placeholder?: string; - search: ((text: string, cb: (arr: any) => any) => void)[]; - max: number[]; - onSelect?: (obj: object, other: any) => void; - renderItem: ((obj: object) => any)[]; - renderItemChoosen: ((el: any) => any)[]; - regexHooked: any; - onChange?: any; - value?: any; - onChangeCurrentList?: any; - hideResult?: any; - onBackspace?: any; - disableNavigationKey?: any; - showResultsOnInit?: any; - position?: any; - onHide?: any; - onEscape?: any; - keyUp?: any; - onKeyUp?: any; - onKeyDown?: any; - onKeyPress?: any; - onPaste?: any; - onFocusChange?: any; - big?: boolean; - small?: boolean; - autoFocus?: any; -}; - -export default class AutoComplete extends Component { - currentIdFromList: string = ''; - is_open: boolean = false; - input: any; - container: any; - outsideClickListener: any; - currentRegexUsed: any = -1; - - constructor(props: any) { - super(props); - - this.state = { - currentList: [], - selected: -1, - resultPosition: '', - selectedUser: {}, - focused: '', - }; - - this.keyUp = this.keyUp.bind(this); - this.keyDown = this.keyDown.bind(this); - } - keyDown(ev: any) { - let key = ev.which || window.event; - - if ( - this.is_open && - key && - this.currentRegexUsed >= 0 && - this.state.currentList.length > 0 && - (key === 13 || key === 9 || key === 38 || key === 40) - ) { - ev.preventDefault(); - ev.stopPropagation(); - } - if (key === 27 && !this.is_open && this.props.onEscape) { - this.props.onEscape(); - } - if (key === 27 && this.is_open && this.props.onHide) { - this.is_open = false; - this.props.onHide(); - } - } - keyUp(ev: any) { - let key = ev.which; - let allText = this.getValueBeforeCaret(); - if (key === 8 && this.input.value.length === 0 && this.props.onBackspace) { - this.props.onBackspace(); - } - for (let i = 0; i < this.props.regexHooked.length; i++) { - let text = allText.match(this.props.regexHooked[i]); - if (text && allText) { - if (this.currentRegexUsed < 0 || this.currentRegexUsed !== i) { - this.currentRegexUsed = i; - } - text = text[1] || ''; - if ( - key && - !this.props.disableNavigationKey && - (key === 13 || key === 9 || key === 38 || key === 40) && - this.state.currentList.length > 0 - ) { - ev.preventDefault(); - ev.stopPropagation(); - if (key === 13 || key === 9) { - //Select (enter) - this.select((this.state.currentList || {})[this.state.selected]); - } else if (key === 38 || key === 40) { - //Up // down - let nextState = 0; - if ( - (key === 38 && this.state.resultPosition === 'top') || - (key === 40 && this.state.resultPosition === 'bottom') - ) { - nextState = (this.state.selected + 1) % this.state.currentList.length; - } else { - nextState = - (this.state.selected + this.state.currentList.length - 1) % - this.state.currentList.length; - } - this.setState({ - selected: nextState, - }); - this.currentIdFromList = this.getCurrentIdFromList(this.state.currentList, nextState); - } - } else { - this.is_open = true; - this.search(text, i); - } - if (this.props.onChangeCurrentList) { - this.props.onChangeCurrentList(this.state.currentList, this.state.selected); - } - return; - } - } - - this.currentRegexUsed = -1; - this.setState({ currentList: [], resultPosition: '' }); - this.props.keyUp && this.props.keyUp(ev); - } - - getCurrentIdFromList(list: any[], pos: number) { - if (!list[pos]) { - return; - } - let id = list[pos].id || JSON.stringify(list[pos]); - return id; - } - - componentWillUnmount() { - document.removeEventListener('click', this.outsideClickListener); - this.input.removeEventListener('keydown', this.keyDown); - this.input.removeEventListener('keyup', this.keyUp); - } - componentDidMount() { - let element = this.container; - this.outsideClickListener = (event: any) => { - if (!element.contains(event.target) && document.contains(event.target)) { - this.setState({ focused: false }); - } - }; - this.outsideClickListener = this.outsideClickListener.bind(this); - document.addEventListener('click', this.outsideClickListener); - - this.input.addEventListener('keydown', this.keyDown); - this.input.addEventListener('keyup', this.keyUp); - - if (this.props.showResultsOnInit) { - this.currentRegexUsed = 0; - this.search('', 0); - this.props.onChangeCurrentList(this.state.currentList, this.state.selected); - } - } - search(query: any, i: any) { - this.props.search[this.currentRegexUsed](query, results => { - if (!this.is_open) { - return; - } - - let suggestions: any[] = []; - for (let j = 0; j < Math.min(this.props.max[this.currentRegexUsed], results.length); j++) { - results[j].autocomplete_id = j; - suggestions.push(results[j]); - } - - let selection = 0; - - const idsFromSuggestedList = suggestions.map( - (item, index) => (item = this.getCurrentIdFromList(suggestions, index)), - ); - - selection = Math.max(idsFromSuggestedList.indexOf(this.currentIdFromList), 0); - - this.currentRegexUsed = i; - this.setState({ - selected: selection, - currentList: suggestions, - }); - - this.currentIdFromList = this.getCurrentIdFromList(suggestions, selection); - - if (this.props.onChangeCurrentList) { - this.props.onChangeCurrentList(suggestions, this.state.selected); - } - }); - } - getValueBeforeCaret() { - return this.input.value.substr(0, this.input.selectionStart); - } - putTextAtCursor(text: string, alreadyTypedLength: any) { - alreadyTypedLength = alreadyTypedLength || 0; - - let myValue = text; - - if (this.input.selectionStart || this.input.selectionStart === '0') { - let startPos = this.input.selectionStart; - let endPos = this.input.selectionEnd; - this.input.value = - this.input.value.substring(0, startPos - alreadyTypedLength) + - myValue + - this.input.value.substring(endPos, this.input.value.length); - this.input.selectionStart = this.input.selectionStart + myValue.length; - this.input.selectionEnd = this.input.selectionStart + myValue.length; - } else { - this.input.value += myValue; - } - - if (this.props.onChange) this.props.onChange({ target: { value: this.input.value } }); - - this.input.focus(); - this.input.dispatchEvent(new Event('input')); - - this.setState({ - selected: -1, - currentList: [], - }); - } - select(item: any) { - if (!item) { - return; - } - - let m = this.getValueBeforeCaret().match(this.props.regexHooked[this.currentRegexUsed]); - if (m === null) { - return; - } - let alreadyTypedLength = m[0].length; - - this.putTextAtCursor( - this.props.renderItemChoosen[this.currentRegexUsed](item), - alreadyTypedLength, - ); - - if (this.props.onSelect) { - this.props.onSelect(item, this.currentRegexUsed); - } - this.is_open = false; - } - setPositionResult() { - if (this.input && this.state.resultPosition === '' && this.state.currentList.length > 0) { - let size = this.state.currentList.length * 32 + 5; - if ( - //@ts-ignore - document.documentElement.clientHeight - window.getBoundingClientRect(this.input).bottom < - size || - this.props.position === 'top' - ) { - this.setState({ resultPosition: 'top' }); - } else { - this.setState({ resultPosition: 'bottom' }); - } - } - } - focus() { - if (!this.input) { - return; - } - this.input.focus(); - this.setState({ focused: true }); - this.keyUp({}); - } - blur() { - this.input.blur(); - this.setState({ focused: false }); - } - setContent(content: any) { - this.input.value = content; - } - render() { - this.setPositionResult(); - return ( -
{ - this.focus(); - this.setState({ focused: true }); - }} - ref={node => (this.container = node)} - > -
- {this.props.autoHeight && ( - { - this.input = ref; - }} - onResize={this.props.onResize} - placeholder={this.props.placeholder} - value={this.props.value} - onChange={this.props.onChange} - onKeyUp={this.props.onKeyUp} - onKeyDown={this.props.onKeyDown} - onKeyPress={this.props.onKeyPress} - onPaste={this.props.onPaste} - onFocus={() => { - if (this.props.onFocusChange) { - this.props.onFocusChange(true); - } - }} - onBlur={() => { - if (this.props.onFocusChange) { - this.props.onFocusChange(false); - } - }} - autoFocus={this.props.autoFocus} - /> - )} - {!this.props.autoHeight && ( - { - this.input = ref; - }} - placeholder={this.props.placeholder} - value={this.props.value} - onChange={this.props.onChange} - onKeyUp={this.props.onKeyUp} - onKeyDown={this.props.onKeyDown} - onKeyPress={this.props.onKeyPress} - onPaste={this.props.onPaste} - onFocus={() => { - if (this.props.onFocusChange) { - this.props.onFocusChange(true); - } - }} - onBlur={() => { - if (this.props.onFocusChange) { - this.props.onFocusChange(false); - } - }} - autoFocus={this.props.autoFocus} - /> - )} - {!this.props.hideResult && this.state.currentList.length > 0 ? ( -
- {this.state.currentList.map((item, index) => { - return ( -
this.select(item)} - > - {item && this.props.renderItem[this.currentRegexUsed](item)} -
- ); - })} -
- ) : ( - '' - )} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/AutoCompleteExtended/AutoCompleteExtended.tsx b/twake/frontend/src/app/components/AutoCompleteExtended/AutoCompleteExtended.tsx deleted file mode 100644 index 2e9105aba1..0000000000 --- a/twake/frontend/src/app/components/AutoCompleteExtended/AutoCompleteExtended.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import React, { useState, ReactElement } from 'react'; -import { AutoComplete } from 'antd'; -import { AutoCompleteProps } from 'antd/lib/auto-complete'; - -const { Option } = AutoComplete; - -export default ( - props: { - maxItems?: number; - render?: (item: any) => ReactElement; - onSearch?: (query: string, callback: (res: any[]) => void) => void; - onSelect?: (id: string) => void; - align?: 'top' | 'bottom'; - } & Omit, -) => { - const [list, setList] = useState([]); - const [inputValue, setInputValue] = useState(''); - - const resetInputValue = () => setInputValue(''); - - return ( - { - props.onSearch && - props.onSearch(text, (res: any[]) => { - setList(res); - }); - }} - value={inputValue} - onSelect={(id: string) => { - resetInputValue(); - props.onSelect && props.onSelect(id); - }} - onChange={e => setInputValue(e || '')} - > - {list.slice(0, props.maxItems || 10).map((item: any) => { - return ( - - ); - })} - - ); -}; diff --git a/twake/frontend/src/app/components/AutoHeight/AutoHeight.js b/twake/frontend/src/app/components/AutoHeight/AutoHeight.js deleted file mode 100755 index e8f2c7785a..0000000000 --- a/twake/frontend/src/app/components/AutoHeight/AutoHeight.js +++ /dev/null @@ -1,93 +0,0 @@ -import React, { Component } from 'react'; -import './AutoHeight.scss'; - -export default class AutoHeight extends Component { - constructor(props) { - super(); - this.change = this.change.bind(this); - } - componentDidMount() { - this.textarea_offset = - parseInt(this.textarea.style.paddingTop || 0) + - parseInt(this.textarea.style.paddingBottom || 0); - window.addEventListener('resize', this.change); - this.change(); - } - componentWillUnmount() { - window.removeEventListener('resize', this.change); - } - change() { - this.textarea.style.height = '1px'; - var totalHeight = this.textarea.scrollHeight - this.textarea_offset; - this.textarea.style.height = totalHeight + 'px'; - this.container.style.height = totalHeight + 'px'; - if (this.oldHeight !== totalHeight && this.props.onResize) { - this.props.onResize(); - } - this.oldHeight = totalHeight; - } - componentDidUpdate(nextProps) { - this.change(); - } - render() { - var className = this.props.className || ''; - - if (this.props.big) { - className += ' big '; - } - if (this.props.medium) { - className += ' medium '; - } - if (this.props.small) { - className += ' small '; - } - - if ( - className.indexOf('medium') === className.indexOf('small') && - className.indexOf('big') === className.indexOf('small') && - className.indexOf('big') < 0 - ) { - className += ' medium'; - } - - return ( -
(this.container = node)} - className={'input autoheight_container ' + className} - style={{ - display: 'inline-block', - width: '100%', - minHeight: this.props.minHeight ? this.props.minHeight : '', - maxHeight: this.props.maxHeight ? this.props.maxHeight : '', - }} - onMouseEnter={() => { - this.change(); - }} - > - -
- ); - } -} diff --git a/twake/frontend/src/app/components/Avatar/Avatar.tsx b/twake/frontend/src/app/components/Avatar/Avatar.tsx deleted file mode 100644 index 67d44eb921..0000000000 --- a/twake/frontend/src/app/components/Avatar/Avatar.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; - -import { Avatar, AvatarProps, Image } from 'antd'; - -import './Avatar.scss'; - -type PropsType = { - url: string; - size?: number; - shape?: AvatarProps['shape']; - borderRadius?: React.CSSProperties['borderRadius']; - fallback?: string; - onClick?: ((event: React.MouseEvent) => void) | undefined; -}; - -const AvatarComponent = ({ url, shape, size, borderRadius, fallback, onClick }: PropsType) => ( -
- - } - /> -
-); - -export default AvatarComponent; diff --git a/twake/frontend/src/app/components/Banner/Banner.scss b/twake/frontend/src/app/components/Banner/Banner.scss deleted file mode 100644 index e513444d6e..0000000000 --- a/twake/frontend/src/app/components/Banner/Banner.scss +++ /dev/null @@ -1,41 +0,0 @@ -.ant-layout-header.banner-container { - padding: 0 16px; - - &.primary { - background-color: var(--primary); - color: var(--white); - } - - &.secondary { - background-color: var(--secondary); - color: var(--white); - border-bottom: 1px solid var(--black); - } - - &.default { - background-color: var(--primary-background); - color: var(--black); - } - - &.warning { - background-color: var(--warning); - color: var(--white); - } - &.important { - background-color: var(--red); - color: var(--white); - } - - &.ghost { - background-color: transparent; - color: var(--black); - } - - .banner-col-icon { - display: flex; - align-items: center; - .icon { - cursor: pointer; - } - } -} diff --git a/twake/frontend/src/app/components/Banner/Banner.tsx b/twake/frontend/src/app/components/Banner/Banner.tsx deleted file mode 100644 index 623c3ef87d..0000000000 --- a/twake/frontend/src/app/components/Banner/Banner.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React, { FC } from 'react'; -import { Col, Layout, Row } from 'antd'; -import './Banner.scss'; -import { X } from 'react-feather'; -import { CSSProperties } from '@material-ui/styles'; - -type PropsType = { - closable?: boolean; - content?: string | JSX.Element; - onClose?: () => any; - height?: string | number; - type: 'primary' | 'secondary' | 'default' | 'warning' | 'important' | 'ghost'; - style?: CSSProperties; - contentColumnStyle?: CSSProperties; - className?: string; -}; - -const Banner: FC = ({ - closable, - content, - onClose, - height, - type, - children, - style, - contentColumnStyle, - className, -}) => { - const headerStyle = { - height: height ? height : 68, - lineHeight: height ? `${height}px` : '68px', - ...style, - }; - - return ( - - - - {content || children || ''} - - {closable && } - - - - ); -}; - -export default Banner; diff --git a/twake/frontend/src/app/components/Buttons/Button.js b/twake/frontend/src/app/components/Buttons/Button.js deleted file mode 100755 index f974972497..0000000000 --- a/twake/frontend/src/app/components/Buttons/Button.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; -import './Buttons.scss'; - -export default class Button extends React.Component { - render() { - var className = this.props.className || ''; - - if (this.props.big) { - className += ' big '; - } - if (this.props.medium) { - className += ' medium '; - } - if (this.props.small) { - className += ' small '; - } - - if ( - className.indexOf('medium') === className.indexOf('small') && - className.indexOf('big') === className.indexOf('small') && - className.indexOf('big') < 0 - ) { - className += ' small'; - } - return ( - - ); - } -} diff --git a/twake/frontend/src/app/components/Buttons/ButtonWithTimeout.js b/twake/frontend/src/app/components/Buttons/ButtonWithTimeout.js deleted file mode 100755 index 3be1d4f750..0000000000 --- a/twake/frontend/src/app/components/Buttons/ButtonWithTimeout.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; - -import Loader from 'components/Loader/Loader.js'; -import Button from './Button.js'; -import './Buttons.scss'; - -export default class ButtonWithTimeout extends React.Component { - /* - props = { - loading : boolean - value : text in button - loadingTimeout : time before show loading - disabled - onClick - style - className - } - */ - constructor(props) { - super(); - this.state = { - showLoader: false, - }; - this.timeout = ''; - } - componentWillUnmount() { - clearTimeout(this.timeout); - } - componentDidUpdate(prevProps, prevState) { - var that = this; - if (prevProps.loading && !this.props.loading) { - if (this.state.showLoader) { - this.setState({ showLoader: false }); - } - clearTimeout(this.timeout); - } else if (!prevProps.loading && this.props.loading) { - this.timeout = setTimeout(function () { - that.setState({ showLoader: true }); - }, this.props.loadingTimeout || 2000); - } - } - render() { - return ( -
- -
- {this.state.showLoader && } -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Buttons/Buttons.scss b/twake/frontend/src/app/components/Buttons/Buttons.scss deleted file mode 100755 index dec37dc2f2..0000000000 --- a/twake/frontend/src/app/components/Buttons/Buttons.scss +++ /dev/null @@ -1,185 +0,0 @@ -.buttonWithTimeout_container { - position: relative; - pointer-events: none; - - & > * { - pointer-events: all; - } - - .buttonWithTimeout { - padding: 0px 35px; - transition: padding 0.5s; - } - .loaderContainer { - color: #fff; - top: 0px; - right: 8px; - position: absolute; - display: inline-block; - transition: opacity 0.5s; - opacity: 0; - height: 100%; - align-items: center; - display: inline-flex; - .loader { - width: 30px; - height: 30px; - } - } - - &.is_loading { - .buttonWithTimeout { - padding-right: 45px; - padding-left: 25px; - } - .loaderContainer { - opacity: 1; - } - } -} - -.button { - background: var(--primary); - color: var(--white); - font-weight: 500; - border: 0px; - border-radius: var(--border-radius-base); - display: inline-block; - vertical-align: middle; - cursor: pointer; - - &:hover { - background: var(--primary-hover); - } - &:active { - background: var(--primary); - } - &:focus { - outline: none; - } - &.disabled, - &:disabled { - background: var(--primary-background); - pointer-events: none; - } - - &.small { - height: 32px; - line-height: 32px; - padding: 0px 8px; - font-size: 14px; - } - - &.medium { - height: 40px; - line-height: 40px; - padding: 0px 12px; - font-size: 16px; - } - - &.big { - height: 64px; - font-size: 18px; - line-height: 64px; - padding: 0px 24px; - } - - &.secondary { - background: #807f8a; - color: var(--white); - - &:hover { - background: #706f79; - } - &:active { - background: #696871; - } - &.disabled, - &:disabled { - background: #bcbcc2; - } - } - - &.danger { - background: #ff1020; - color: var(--white); - - &:hover { - background: #f00010; - } - &:active { - background: #d80000; - } - &.disabled, - &:disabled { - background: #ffa0a0; - } - } - - &.secondary-light { - background: var(--grey-light); - color: var(--black); - - &:hover, - &:active { - opacity: 0.9; - } - &.disabled, - &:disabled { - background: var(--grey-background); - color: var(--grey-dark); - } - } - - &.primary-text { - background: transparent; - color: var(--primary); - font-size: 12px; - padding: 0 2px; - .m-icon-small { - font-size: 14px !important; - &:before { - margin: 0px; - } - } - &.disabled, - &:disabled { - color: var(--primary-background); - } - &:hover { - color: var(--primary-hover); - // background: var(--primary-background); - } - &:active { - // background: var(--primary-background); - } - } - - &.secondary-text { - background: transparent; - color: var(--grey-dark); - font-size: 12px; - padding: 0 2px; - .m-icon-small { - font-size: 14px !important; - &:before { - margin: 0px; - } - } - &.disabled, - &:disabled { - color: var(--primary-background); - } - &:hover { - color: var(--black); - //background: var(--grey-background); - } - &:active { - color: var(--black); - } - } - - .m-icon-small { - height: 100%; - } -} diff --git a/twake/frontend/src/app/components/Calendar/CalendarSelector/CalendarSelector.js b/twake/frontend/src/app/components/Calendar/CalendarSelector/CalendarSelector.js deleted file mode 100755 index a05a185094..0000000000 --- a/twake/frontend/src/app/components/Calendar/CalendarSelector/CalendarSelector.js +++ /dev/null @@ -1,167 +0,0 @@ -import React from 'react'; -import './CalendarSelector.scss'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Select from 'components/Select/Select.js'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import WorkspacesService from 'services/workspaces/workspaces.js'; -import Languages from 'services/languages/languages'; - -export default class CalendarSelector extends React.Component { - constructor(props) { - super(); - this.props = props; - - this.state = { - selected: [], - }; - } - - delete(item) { - var list = this.props.value.map(item => item.calendar_id); - const index = list.indexOf(item.id); - if (index >= 0) { - list.splice(index, 1); - this.change(list); - } - MenusManager.closeMenu(); - } - - openMenu(evt, item) { - if (this.props.readonly) { - return; - } - MenusManager.openMenu( - [ - { - className: 'error', - icon: 'trash', - text: Languages.t('components.calendar.calendarselector.remove', [], 'Retirer'), - onClick: () => { - this.delete(item); - }, - }, - ], - { x: evt.clientX, y: evt.clientY, width: 150 }, - 'bottom', - ); - } - - change(list) { - if (this.props.onChange) - this.props.onChange( - list - .map(id => { - var cal = Collections.get('calendars').find(id); - if (!cal) { - return undefined; - } - return { - calendar_id: cal.id, - workspace_id: cal.workspace_id, - }; - }) - .filter(item => item), - ); - } - - render() { - var nb_known_workspaces = 0; - var external_workspace = null; - - return ( -
-
- {this.props.value.map(ws_cal_id => { - if (ws_cal_id.workspace_id) { - if (WorkspacesService.user_workspaces[ws_cal_id.workspace_id]) { - external_workspace = Collections.get('workspaces').find(ws_cal_id.workspace_id); - } - } - - var item = Collections.get('calendars').find(ws_cal_id.calendar_id); - if (!item || item.workspace_id !== WorkspacesService.currentWorkspaceId) { - return ''; - } - nb_known_workspaces++; - return ( -
(this.node = node)} - onClick={evt => this.openMenu(evt, item)} - className={'calendar_item ' + (this.props.readonly ? '' : 'removable')} - > -
- {'' + item.title} -
- ); - })} - - {(!this.props.value || this.props.value.length === 0) && ( -
- {Languages.t( - 'components.calendar.calendarselector.no_workspace_calendar', - [], - "Aucun calendrier d'espace de travail.", - )} -
- )} -
- - {!this.props.readonly && ( -
- this.input.blur()} - onEnter={() => this.input.blur()} - onBlur={() => this.blur()} - onFocus={() => this.focus()} - placeholder={'No date'} - value={this.state.time_ts ? this.state.time_string : ''} - style={{ maxWidth: 108 }} - onChange={evt => this.process(evt.target.value)} - refInput={node => (this.input = node)} - big={this.props.big} - medium={this.props.medium} - small={this.props.small} - /> - {this.props.withReset && ( -
{ - this.setState({ time_ts: false }); - this.props.onChangeBlur(this.state.time_ts); - this.setState({}); - }} - > - -
- )} - -
- ); - } -} diff --git a/twake/frontend/src/app/components/Calendar/DayPicker/DayPicker.js b/twake/frontend/src/app/components/Calendar/DayPicker/DayPicker.js deleted file mode 100755 index 0ab9dadac5..0000000000 --- a/twake/frontend/src/app/components/Calendar/DayPicker/DayPicker.js +++ /dev/null @@ -1,165 +0,0 @@ -import React, { Component } from 'react'; -import Icon from 'components/Icon/Icon.js'; -import moment from 'moment'; -import './DayPicker.scss'; - -export default class DayPicker extends React.Component { - /* - this.props :{ - onChange(day) - value : Array of selected days - } - */ - constructor(props) { - super(props); - this.state = { - days: [], - currentDate: moment(), - }; - this.openSelected = false; - window.moment = moment; - } - componentWillUnmount() {} - componentDidMount() { - this.setState(this.updateDay()); - } - componentWillUpdate(nextProps, nextState) { - if (moment(nextProps.value).valueOf() != this.oldProp) { - var obj = this.updateDay(nextProps.value); - nextState.days = obj.days; - nextState.currentDate = obj.currentDate; - } - this.oldProp = moment(nextProps.value).valueOf(); - } - updateDay(date) { - var searchedDate = date || moment(); - var days = []; - var first_day_of_month = moment(searchedDate).startOf('month').startOf('week'); - for (var i = 0; i < 35; i++) { - days.push(moment(moment(first_day_of_month).add(i, 'days'))); - } - return { - days: days, - currentDate: searchedDate, - }; - } - isSelected(day) { - if (this.props.value) { - if ( - Array.isArray(this.props.value) && - this.props.value.length == 2 && - this.props.value[0] && - this.props.value[1] - ) { - return day.isBetween(this.props.value[0], this.props.value[1], 'day', '[]'); - } else if ( - Array.isArray(this.props.value) && - this.props.value.length >= 1 && - this.props.value[0] - ) { - return day.isSame(this.props.value[0], 'day'); - } else if (!Array.isArray(this.props.value) && this.props.value) { - return day.isSame(this.props.value, 'day'); - } - } - return false; - } - isLast(day) { - if (this.props.value) { - if ( - Array.isArray(this.props.value) && - this.props.value.length == 2 && - this.props.value[0] && - this.props.value[1] - ) { - return day.isSame(this.props.value[1], 'day'); - } else if ( - Array.isArray(this.props.value) && - this.props.value.length >= 1 && - this.props.value[0] - ) { - return day.isSame(this.props.value[0], 'day'); - } else if (!Array.isArray(this.props.value) && this.props.value) { - return day.isSame(this.props.value, 'day'); - } - } - return false; - } - render() { - var that = this; - var last_week = -1; - return ( -
this.props.onClick && this.props.onClick()} - onMouseDown={this.props.onMouseDown} - > -
-
{moment(this.state.currentDate).format('MMMM YYYY')}
-
-
{ - this.setState(this.updateDay(moment(this.state.currentDate).subtract(1, 'months'))); - }} - > - -
-
{ - this.setState(this.updateDay(moment(this.state.currentDate).add(1, 'months'))); - }} - > - -
-
-
-
-
- Wk -
- {this.state.days.map((day, index) => { - if (index < 7) { - return ( -
- {day.format('ddd')} -
- ); - } - })} - {this.state.days.map((day, index) => { - var list = []; - if (day.week() != last_week) { - last_week = day.week(); - list.push(
{last_week}
); - } - list.push( -
{ - if (this.props.onChange) { - this.props.onChange(day); - } - }} - className={ - 'day ' + - (day.month() == this.state.currentDate.month() ? '' : 'notInMonth') + - ' ' + - (day.format('YYYY MM DD') == moment().format('YYYY MM DD') ? 'today' : '') + - ' ' + - (this.isSelected(day) ? 'selected' : '') + - ' ' + - (this.isLast(day) ? 'last' : '') - } - > - {day.date()} -
, - ); - return list; - })} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Calendar/Event/Event.js b/twake/frontend/src/app/components/Calendar/Event/Event.js deleted file mode 100755 index 44469bd2d7..0000000000 --- a/twake/frontend/src/app/components/Calendar/Event/Event.js +++ /dev/null @@ -1,136 +0,0 @@ -import React, { Component } from 'react'; -import './Event.scss'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Icon from 'components/Icon/Icon.js'; -import CalendarService from 'services/Apps/Calendar/Calendar.js'; -import Languages from 'services/languages/languages'; -import UserListManager from 'components/UserListManager/UserListManager'; - -import moment from 'moment'; - -export default class Event extends React.Component { - constructor(props) { - super(); - this.props = props; - } - render() { - var className = ''; - var hiddenClass = ''; - var icon = ''; - var date; - var icon_location = ''; - var icon_description = ''; - var event_duration = ''; - var count = 0; - var style; - var classNameUser = ''; - if (this.props.inEvent) { - classNameUser = 'inEvent'; - } - - var event_name = - this.props.event.title || Languages.t('scenes.apps.drive.navigators.new_file.untitled'); - - var event_start = moment(parseInt(this.props.event.from) * 1000).format('LT'); - - var event_end = moment(parseInt(this.props.event.to) * 1000).format('LT'); - - var location = this.props.event.location || ''; - - var description = this.props.event.description; - - if (description) icon_description = 'subject'; - if (location) icon_location = 'location-point'; - - if (event_start) event_duration = event_start; - if (event_end) - event_duration = - event_duration + Languages.t('components.calendar.event.to', [], ' à ') + event_end; - - var duration = (parseInt(this.props.event.to) - parseInt(this.props.event.from)) / 60; - - if ( - (duration > 0 && duration <= 15) || - this.props.event.type == 'deadline' || - this.props.event.type == 'remind' - ) { - className += ' size_15 '; - } else if ((duration > 15 && duration <= 30) || this.props.event.all_day) { - className += ' size_30'; - if (location) event_duration += ', ' + location; - } else if (duration > 30 && duration <= 45) { - className += ' size_45'; - } else if (duration > 45 && duration <= 60) { - className += ' size_60'; - } - - className += ' ' + this.props.event.type; - - if (this.props.event.type == 'remind') { - icon = 'stopwatch'; - } else if (this.props.event.type == 'deadline') { - icon = 'stopwatch-slash'; - } else if (this.props.event.type == 'move') { - icon = 'car-sideview'; - } - - var readonly = CalendarService.getIsReadonly(this.props.event); - - var users = []; - var emails = []; - - (this.props.event.participants || []).map(obj => { - if (obj) { - var regex = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; - if (obj.user_id_or_mail.match(regex)) { - var user = Collections.get('users').find(obj.user_id_or_mail); - users.push(user); - } else { - var email = obj.user_id_or_mail; - emails.push(email); - } - } - }); - - return ( -
-
- {icon && } - - - {event_name} - - {(duration <= 30 || this.props.event.all_day) && ', ' + event_start} - - -
- - {duration > 30 && !this.props.event.all_day && ( -
- {event_duration} -
- )} - -
- {'' + location} -
- -
- { - return { id: u.user_id_or_mail }; - })} - max={4} - readOnly - collapsed - medium - /> -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.js b/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.js deleted file mode 100755 index 5cdc7e22c9..0000000000 --- a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.js +++ /dev/null @@ -1,277 +0,0 @@ -import React, { Component } from 'react'; -import './RepetitionPopup.scss'; -import Input from 'components/Inputs/Input.js'; -import Select from 'components/Select/Select.js'; -import Languages from 'services/languages/languages'; -import { RRule } from 'rrule'; -import moment from 'moment'; -import Radio from 'components/Inputs/Radio.js'; -import DatePicker from 'components/Calendar/DatePicker.js'; -import Button from 'components/Buttons/Button.js'; - -export default class RepetitionSelector extends React.Component { - constructor(props) { - super(); - this.props = props; - this.state = { - value: this.props.value, - date: this.props.date, - radio: 1, - ts: this.props.date, - i18n: Languages, - value_monthly: 'select1' || undefined, - every_month: undefined, - rrule_interval: undefined, - rrule_count: undefined, - selected: [false, false, false, false, false, false, false], - colorBack: '#FFFFF', - colorFont: '#837dff', - }; - this.days = []; - Languages.addListener(this); - this.rule = new RRule(); - moment.updateLocale({ - week: { - dow: 1, - }, - }); - } - - componentWillUnmount() { - Languages.removeListener(this); - } - - render() { - return ( -
-
- {Languages.t('components.calendar.repetition.custom_recurrence')} -
- -
- - {Languages.t('components.calendar.repetition.repeat')} - - this.setState({ rrule_interval: evt.target.value })} - /> - { - this.setState({ value_monthly: v }); - }} - /> -
- -
-
- {Languages.t('components.calendar.repetition.ends')} -
- -
- this.setState({ radio: 1 })} - /> -
-
- -
- this.setState({ radio: 2 })} - /> -
- this.setState({ ts: value })} - /> -
-
- -
- this.setState({ radio: 3 })} - /> -
- this.setState({ rrule_count: evt.target.value })} - /> - {Languages.t('components.calendar.repetition.occurrence')} -
-
-
- -
- - -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.scss b/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.scss deleted file mode 100755 index e92c10781a..0000000000 --- a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionPopup.scss +++ /dev/null @@ -1,76 +0,0 @@ -.repetition_popup { - font-weight: 500; - - .title { - font-size: 22px; - margin-bottom: 24px; - } - - .week_day { - height: 40px; - padding-top: 6px; - box-sizing: border-box; - - div { - width: 25px; - line-height: 25px; - text-align: center; - border-radius: 25px; - display: inline-block; - vertical-align: middle; - padding-top: 1px; - box-sizing: border-box; - font-size: 12px; - font-weight: 500; - cursor: pointer; - } - } - - .selectedColor { - background-color: var(--primary); - color: var(--grey-background); - } - - .unselectedColor { - background-color: var(--grey-background); - color: var(--primary); - - &:hover { - background: var(--primary-background); - } - } - - .popup_line { - input { - width: 100px; - } - - .onDate, - .after { - .radio_with_label { - width: 100px; - } - } - - .onDate { - display: flex; - justify-content: space-between; - width: 100%; - } - .datePicker { - display: inline-block; - } - - .after { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - } - } - - .buttons { - display: flex; - justify-content: flex-end; - } -} diff --git a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionSelector.js b/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionSelector.js deleted file mode 100755 index 6e07ba067b..0000000000 --- a/twake/frontend/src/app/components/Calendar/RepetitionSelector/RepetitionSelector.js +++ /dev/null @@ -1,123 +0,0 @@ -import React, { Component } from 'react'; -import Select from 'components/Select/Select.js'; -import Languages from 'services/languages/languages'; -import moment from 'moment'; -import MediumPopupManager from 'app/components/Modal/ModalManager'; -import Repetitionpopup from 'components/Calendar/RepetitionSelector/RepetitionPopup.js'; - -export default class RepetitionSelector extends React.Component { - constructor(props) { - super(); - this.props = props; - - this.state = { - value: this.props.value, - date: this.props.date, - // rruleObject: rrulestr(this.props.rrule).options, - i18n: Languages, - }; - - Languages.addListener(this); - this.options = [ - { - // "text": moment(this.state.date).format(), - text: Languages.t('components.calendar.repetition.does_not_repeat'), - value: 'select1', - }, - { - text: Languages.t('components.calendar.repetition.everyday'), - value: 'DTSTART:' + moment(this.state.date).format() + '\nRRULE:FREQ=WEEKLY', - }, - { - text: Languages.t('components.calendar.repetition.weekly_on', [ - moment(this.state.date).format('dddd'), - ]), - value: - 'DTSTART:' + - moment(this.state.date).format() + - '\nRRULE:FREQ=WEEKLY;BYDAY=' + - moment(this.state.date).format('dd').toUpperCase(), - }, - { - text: Languages.t('components.calendar.repetition.monthly_on', [ - moment - .localeData() - .ordinal( - moment(this.state.date).week() - moment(this.state.date).startOf('month').week() + 1, - ), - moment(this.state.date).format('dddd'), - ]), - value: - 'DTSTART:' + - moment(this.state.date).format() + - '\nFREQ=MONTHLY;BYDAY=+' + - (moment(this.state.date).week() - moment(this.state.date).startOf('month').week() + 1) + - moment(this.state.date).format('dd').toUpperCase(), - }, - { - text: Languages.t('components.calendar.repetition.annually_on', [ - moment(this.state.date) - .format('LL') - .replace(moment(this.state.date).format('YYYY'), '') - .replace(/,/, ''), - ]), - value: - 'DTSTART:' + - moment(this.state.date).format() + - '\nRRULE:FREQ=YEARLY;BYMONTH=' + - moment(this.state.date).format('M') + - ';BYMONTHDAY=' + - moment(this.state.date).format('M'), - }, - { - text: Languages.t('components.calendar.repetition.every_weekday'), - value: - 'DTSTART:' + - moment(this.state.date).format() + - '\nRRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR', - }, - ]; - - if (this.props.rrule !== undefined) { - this.options.push({ - text: Languages.t('components.calendar.repetition.custom'), - value: this.props.rrule + 'customSelect', - }); - } else { - this.options.push({ - text: Languages.t('components.calendar.repetition.custom'), - value: 'customSelect', - }); - } - } - - render() { - return ( -
- this.blur()} - onFocus={() => (this.focus = true)} - value={this.state.time_string} - style={{ maxWidth: 94 }} - onChange={evt => this.process(evt.target.value)} - /> - -
- ); - } -} diff --git a/twake/frontend/src/app/components/ColorPicker/ColorPicker.js b/twake/frontend/src/app/components/ColorPicker/ColorPicker.js deleted file mode 100755 index b19b376dc5..0000000000 --- a/twake/frontend/src/app/components/ColorPicker/ColorPicker.js +++ /dev/null @@ -1,53 +0,0 @@ -import React, { Component } from 'react'; -import './ColorPicker.scss'; -import CheckIcon from '@material-ui/icons/CheckOutlined'; - -export default class ColorPicker extends React.Component { - static colors = [ - '#D50000', - '#E67C73', - '#F4511E', - '#F6BF26', - '#33B679', - '#0B8043', - '#039BE5', - '#3F51B5', - '#7986CB', - '#8E24AA', - '#801515', - '#616161', - ]; - - /* - props = { - value : default color - onChange : called when a color is selected - } - */ - constructor(props) { - super(); - this.colors = ColorPicker.colors; - } - render() { - var showed_selected = this.colors.indexOf(this.props.value) >= 0; - var colors = this.colors; - if (!showed_selected) { - var colors = this.colors.concat([this.props.value]); - } - return ( -
- {colors.map(color => { - return ( -
this.props.onChange(color)} - > - {this.props.value == color && } -
- ); - })} -
- ); - } -} diff --git a/twake/frontend/src/app/components/CompanyMessagesCounter/CompanyMessagesCounter.tsx b/twake/frontend/src/app/components/CompanyMessagesCounter/CompanyMessagesCounter.tsx deleted file mode 100644 index 8d2cd3e40d..0000000000 --- a/twake/frontend/src/app/components/CompanyMessagesCounter/CompanyMessagesCounter.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Col, Progress, Row, Typography } from 'antd'; -import './CompanyMessagesCounter.scss'; -import i18n from 'i18next'; - -import Languages from 'services/languages/languages'; -import InitService from 'services/InitService'; -import { useCurrentCompany } from 'app/state/recoil/hooks/useCompanies'; -import FeatureTogglesService, { FeatureNames } from 'app/services/FeatureTogglesService'; -import MessageHistoryService from 'app/services/Apps/Messages/MessageHistoryService'; - -const { Text, Title, Link } = Typography; -const CompanyMessagesCounter = () => { - const [messagesCount, setMessagesCount] = useState(1); - let companyMessagesLimit = MessageHistoryService.getLimitCompanyMessages(); - - const { company } = useCurrentCompany(); - - const companySubscriptionUrl = - InitService.server_infos?.configuration.accounts.console?.company_subscription_url || ''; - - const onClickLink = () => window.open(companySubscriptionUrl, 'blank'); - - useEffect(() => { - if (company) { - setMessagesCount(company.stats?.total_messages || 1); - } - }, [company]); - - return !FeatureTogglesService.getFeatureValue(FeatureNames.MESSAGE_HISTORY) ? ( - <> - - - - {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_header', [])} - - - {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_info', [ - Intl.NumberFormat(i18n.language).format(companyMessagesLimit), - ])} - -
- - {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_link', [])} - -
- - - (messagesCount / 1000).toFixed(1) + 'k'} - percent={(messagesCount / companyMessagesLimit) * 100} - width={55} - /> - -
- - ) : ( - <> - ); -}; -export default CompanyMessagesCounter; diff --git a/twake/frontend/src/app/components/ComponentsTester/ComponentDoc.js b/twake/frontend/src/app/components/ComponentsTester/ComponentDoc.js deleted file mode 100755 index e00dedd74f..0000000000 --- a/twake/frontend/src/app/components/ComponentsTester/ComponentDoc.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { Component } from 'react'; -import InputWithClipBoard from 'components/InputWithClipBoard/InputWithClipBoard.js'; -import './ComponentDoc.scss'; - -export default class ComponentDoc extends React.Component { - constructor() { - super(); - } - render() { - return ( -
-
- {this.props.title &&
{this.props.title}
} - {this.props.import && ( - - )} -
-
{this.props.children}
-
- {this.props.properties && [ -
Properties
, - - - - - - - - - - {this.props.properties.map(property => { - return ( - - - - - - - ); - })} -
PropertyTypeDefaultDescription
{property[0]} - {property[1].split(',').map(item => ( - {item} - ))} - {property[2]}{property[3]}
, -
, -
, - ]} - - {this.props.infos && [ -
Infos
, -
{this.props.infos}
, - ]} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/ComponentsTester/ComponentsTester.js b/twake/frontend/src/app/components/ComponentsTester/ComponentsTester.js deleted file mode 100755 index 7394524a3a..0000000000 --- a/twake/frontend/src/app/components/ComponentsTester/ComponentsTester.js +++ /dev/null @@ -1,369 +0,0 @@ -import React, { Component } from 'react'; -import Emojione from 'components/Emojione/Emojione'; -import Icon from 'components/Icon/Icon.js'; -import Menu from 'components/Menus/Menu.js'; -import MenusBodyLayer from 'components/Menus/MenusBodyLayer.js'; -import AutoComplete from 'components/AutoComplete/AutoComplete'; -import UserPicker from 'components/UserPicker/UserPicker.js'; -import EmojiPicker from 'components/EmojiPicker/EmojiPicker.js'; - -import Directory from 'components/Drive/Directory.js'; -import File from 'components/Drive/File'; -import DriveMultiSelector from 'components/Drive/DriveMultiSelector.js'; - -import Rounded from 'components/Inputs/Rounded.js'; - -import DraggableBodyLayer from 'components/Draggable/DraggableBodyLayer.js'; - -import emojiService from 'services/emojis/emojis.js'; -import User from 'components/ui/User.js'; - -import AutoHeight from 'components/AutoHeight/AutoHeight.js'; -import Tooltip from 'components/Tooltip/Tooltip.js'; -import InputWithClipBoard from 'components/InputWithClipBoard/InputWithClipBoard.js'; - -import './ComponentsTester.scss'; -import GroupInputs from './Group/Inputs.js'; - -export default class ComponentsTester extends React.Component { - constructor() { - super(); - this.state = { - autocompValue: '', - visible: false, - }; - } - render() { - return [ -
-
-
Test des composants
-
ctrl+alt+e pour revenir à Twake
-
- - - -
-
Icones
- -
- Title -
-
- Sub title -
-
- Text -
-
- -
-
Emojione
-
- Title -
-
- Subtitle -
-
- Text -
-
-
-
Tooltip
-
- (this.tooltip = o)} - tooltip={'toolltiiiiiiiiip'} - position={'top'} - overable={false} - > -
this is my tooltip top
-
-
- -
- -
this is my tooltip top
-
-
-
- -
-
Input with clipboard
-
- -
-
- -
-
Menus
- - salut
, - }, - ], - }, - { type: 'separator' }, - { type: 'text', text: 'Du texte' }, - ]} - > - Click here ! - -
-
-
Auto complete one line
- { - cb( - [ - { - id: 1, - username: 'benoit', - mail: 'benoit.tallandier@g.a', - userimage: 'https://randomuser.me/api/portraits/men/40.jpg', - }, - { - id: 2, - username: 'romaric', - mail: 'romaric.mourgues@g.a', - userimage: 'https://randomuser.me/api/portraits/men/41.jpg', - }, - { - id: 3, - username: 'guillaume', - mail: 'romaric.mourgues@g.a', - userimage: 'https://randomuser.me/api/portraits/men/42.jpg', - }, - { - id: 4, - username: 'Amandine', - mail: 'romaric.mourgues@g.a', - userimage: 'https://randomuser.me/api/portraits/women/40.jpg', - }, - ].filter(function (item) { - if (item && item.username.indexOf(text) !== -1) { - return true; - } - return false; - }), - ); - }, - (text, cb) => { - cb(emojiService.search(text)); - }, - ]} - max={[5, 5]} - renderItemChoosen={[ - item => { - return '@' + (item || {}).username + ' '; - }, - item => { - return item.shortname + ' '; - }, - ]} - renderItem={[ - item => { - return ( -
- -
- ); - }, - item => { - return ( -
- {item.shortname} -
- ); - }, - ]} - regexHooked={[/\B@([\-+\w]*)$/, /\B:([\-+\w]{0}[\-+\w]*)$/]} - placeholder="Placeholder" - autoHeight - /> -
-
-
Multi-line input
- - -
-
-
Users picker
-
In menu
- this.setState({ users_picker_value: list })} - /> - ), - }, - ]} - > -
Open menu
-
- -
-
-
Inline
- - this.setState({ users_picker_value: list })} - inline - /> - -
-
Inline read only
- - - -
-
Inline read only miniatures
- - -
-
-
Emoji picker
- }]}> - Click here ! - -
- -
- - -
Drive
- -
- TODO: Tester drag drop depuis ordinateur -
- TODO: Faire apparaitre l'icone "drag + menu" au survol -
- - -
-
Dossiers
- - - - - - - - - -
-
- -
Fichiers
- - - - - - - - - -
-
-
-
, - , - , - ]; - } -} diff --git a/twake/frontend/src/app/components/ComponentsTester/Group/Inputs.js b/twake/frontend/src/app/components/ComponentsTester/Group/Inputs.js deleted file mode 100755 index f1fe20aad8..0000000000 --- a/twake/frontend/src/app/components/ComponentsTester/Group/Inputs.js +++ /dev/null @@ -1,123 +0,0 @@ -import React, { Component } from 'react'; - -import Checkbox from 'components/Inputs/Checkbox.js'; -import Switch from 'components/Inputs/Switch'; -import Button from 'components/Buttons/Button.js'; -import Input from 'components/Inputs/Input.js'; - -import StepCounter from 'components/StepCounter/StepCounter.js'; -import Languages from 'services/languages/languages'; -import { lang } from 'moment'; - -export default class GroupInputs extends React.Component { - constructor() { - super(); - this.state = { - input: 'Example', - }; - } - render() { - return [ -
-
Formulaires
- -
className="big"
- this.setState({ input: evt.target.value })} - /> -
- this.setState({ input: value })} - /> -
- this.setState({ input: value })} - /> -
- -
className="medium"
- this.setState({ input: evt.target.value })} - /> -
- this.setState({ input: value })} - /> -
- this.setState({ input: value })} - /> -
- -
className="small"
- this.setState({ input: evt.target.value })} - /> -
- this.setState({ input: value })} - /> -
- this.setState({ input: value })} - /> -
-
, -
-
- -
Create my company 3/4
-
- {Languages.t( - 'scenes.app.workspaces.create_company.importations.title_1', - [], - 'Already working with digital tools? Import or integrate your tools now!', - )} -
- {Languages.t( - 'scenes.app.workspaces.create_company.importations.title_2', - [], - 'No worries, you can do this later!', - )} -
- -
-
-
What's your company name ?
- this.setState({ company_name: evt.target.value })} - placeholder="Ex : Google, Aircall, Doctolib" - /> -
-
- -
-
-
-
, - ]; - } -} diff --git a/twake/frontend/src/app/components/Configurators/ConfigBodyLayer.js b/twake/frontend/src/app/components/Configurators/ConfigBodyLayer.js deleted file mode 100755 index b49f417baa..0000000000 --- a/twake/frontend/src/app/components/Configurators/ConfigBodyLayer.js +++ /dev/null @@ -1,116 +0,0 @@ -import React, { Component } from 'react'; - -import ConfiguratorsManager from 'services/Configurators/ConfiguratorsManager.js'; -import Twacode from 'components/Twacode/Twacode'; -import WorkspacesApps from 'services/workspaces/workspaces_apps.js'; -import CloseIcon from '@material-ui/icons/CloseOutlined'; -import './Configurators.scss'; - -/* - Where the configurators will be displayed, this component should be in app.js (menus should be over all elements of the page) -*/ -export default class ConfigBodyLayer extends React.Component { - constructor(props) { - super(); - this.state = {}; - ConfiguratorsManager.addListener(this); - } - componentWillUnmount() { - ConfiguratorsManager.removeListener(this); - clearTimeout(this.loading_interaction_timeout); - } - componentWillMount() { - this.generateData(); - } - shouldComponentUpdate(nextProps, nextState) { - this.generateData(); - var string = JSON.stringify(this.configurator); - if (string != this.saved) { - nextState.loading_interaction = false; - clearTimeout(this.loading_interaction_timeout); - this.saved = string; - return true; - } - return nextState.loading_interaction ? true : false; - } - generateData() { - if (ConfiguratorsManager.configurator_order.length == 0) { - this.configurator = null; - } - this.configurator = - ConfiguratorsManager.currentConfigurators[ - ConfiguratorsManager.configurator_order[ConfiguratorsManager.configurator_order.length - 1] - ]; - } - onAction(type, id, context, passives, evt) { - if (type == 'interactive_action') { - this.setState({ loading_interaction: true }); - clearTimeout(this.loading_interaction_timeout); - this.loading_interaction_timeout = setTimeout(() => { - this.setState({ loading_interaction: false }); - }, 5000); - var app_id = this.configurator.app.id; - var type = 'interactive_configuration_action'; - var event = id; - var data = { - interactive_context: context, - form: passives, - hidden_data: this.configurator.hidden_data, - }; - WorkspacesApps.notifyApp(app_id, type, event, data); - } - } - render() { - if (!this.configurator) { - return ''; - } - - return ( -
-
-
-
-
-
-
{this.configurator.app.identity?.name}
- - { - ConfiguratorsManager.closeConfigurator(this.configurator.app); - }} - /> -
-
- - this.onAction(type, id, context, passives, evt) - } - /> -
-
-
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Configurators/Configurators.scss b/twake/frontend/src/app/components/Configurators/Configurators.scss deleted file mode 100755 index f056a65a10..0000000000 --- a/twake/frontend/src/app/components/Configurators/Configurators.scss +++ /dev/null @@ -1,60 +0,0 @@ -.config_modal { - height: 100%; - width: 100%; - background: rgba(255, 255, 255, 0.5); - position: absolute; - z-index: 10; - top: 0; - - .modal { - width: 0px; - height: 0px; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - .component { - background: white; - border-radius: var(--border-radius-base); - box-shadow: var(--box-shadow-base); - position: relative; - display: inline-flex; - flex-direction: column; - transform: translateX(-50%) translateY(-50%); - .header { - padding: 15px; - border-bottom: 1px solid #ddd; - display: flex; - - .app_logo { - height: 30px; - width: 30px; - background-size: contain; - background-position: center; - border-radius: var(--border-radius-base); - margin-right: 5px; - } - .app_name { - line-height: 30px; - flex: auto; - } - .close { - margin: 2px; - opacity: 0.5; - cursor: pointer; - &:hover { - opacity: 1; - } - } - } - .content { - flex: 1; - overflow: auto; - padding: 15px; - box-sizing: border-box; - } - } - } -} diff --git a/twake/frontend/src/app/components/ConnectionIndicator/ConnectionIndicator.tsx b/twake/frontend/src/app/components/ConnectionIndicator/ConnectionIndicator.tsx deleted file mode 100644 index ce8f292f5e..0000000000 --- a/twake/frontend/src/app/components/ConnectionIndicator/ConnectionIndicator.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React, { useEffect } from 'react'; -import './ConnectionIndicator.scss'; -import ErrorOutlinedIcon from '@material-ui/icons/ErrorOutlined'; -import HourglassEmpty from '@material-ui/icons/HourglassEmpty'; -import CheckCircleIcon from '@material-ui/icons/CheckCircle'; -import Languages from 'services/languages/languages'; -import { ConnectedState } from '../../state/recoil/atoms/Connected'; -import { useRecoilState } from 'recoil'; -import WebSocket, { WebsocketEvents } from 'services/WebSocket/WebSocket'; - -export default () => { - const [{ connected, reconnecting }, setState] = useRecoilState(ConnectedState); - - useEffect(() => { - WebSocket.get().on(WebsocketEvents.Disconnected, () => { - setState({ connected: false, reconnecting: false }); - }); - WebSocket.get().on(WebsocketEvents.Connected, () => { - setState({ connected: true, reconnecting: false }); - }); - }, [setState]); - - return ( -
- {connected === false && reconnecting !== true && ( -
- {Languages.t('general.connexion_status.disconnected')} -
- )} - {connected === false && reconnecting === true && ( -
- {Languages.t('general.connexion_status.connecting')} -
- )} - {connected === true && ( -
- {Languages.t('general.connexion_status.connected')} -
- )} -
- ); -}; diff --git a/twake/frontend/src/app/components/ConnectorsListManager/ConnectorsListManager.js b/twake/frontend/src/app/components/ConnectorsListManager/ConnectorsListManager.js deleted file mode 100755 index 9af487cab7..0000000000 --- a/twake/frontend/src/app/components/ConnectorsListManager/ConnectorsListManager.js +++ /dev/null @@ -1,139 +0,0 @@ -import React, { Component } from 'react'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import CloseIcon from '@material-ui/icons/CloseOutlined'; -import AddIcon from '@material-ui/icons/AddOutlined'; -import GearIcon from '@material-ui/icons/BuildOutlined'; -import Input from 'components/Inputs/Input.js'; -import './ConnectorsListManager.scss'; -import Languages from 'services/languages/languages'; -import WorkspacesApps from 'services/workspaces/workspaces_apps.js'; -import { getCompanyApplication as getApplication } from 'app/state/recoil/atoms/CompanyApplications'; - -export default class ConnectorsListManager extends React.Component { - constructor(props) { - super(); - this.props = props; - this.state = { - connectors_ids: props.current.map(item => item.id), - filtered: [], - input: '', - }; - } - filter(text) { - this.state.input = text; - var list = this.props.list; - var res = list - .filter(el => { - return el.identity.name.toLocaleLowerCase().indexOf(text.toLocaleLowerCase()) >= 0; - }) - .map(el => el); - this.setState({ filtered: res }); - } - componentDidMount() { - this.filter(''); - } - - renderLine(item, added) { - var id = item.id || item; - - item = getApplication(id); - - var text = ''; - var button = ''; - - text = ( -
- {WorkspacesApps.getAppIconComponent(item)} - {item.identity.name} -
- ); - - if (added) { - button = ( -
- { - this.props.onConfig(item); - }} - /> - { - this.state.connectors_ids = this.state.connectors_ids.filter(id => - typeof item == 'string' ? item != id : item.id != id, - ); - this.setState({}); - this.props.onChange(this.state.connectors_ids); - }} - /> -
- ); - } else { - button = ( -
- { - this.state.connectors_ids.push(item.id || this.state.input.toLocaleLowerCase()); - this.setState({ input: '' }); - this.props.onChange(this.state.connectors_ids); - }} - /> -
- ); - } - - return ( -
- {text} - {button} -
- ); - } - render() { - return ( -
-
-
- {Languages.t('scenes.apps.tasks.connectors_menu', [], 'Connecteurs')} -
-
- - {this.state.connectors_ids.length == 0 && ( -
- {Languages.t('scenes.apps.tasks.no_connector', [], 'Aucun connecteurs.')} -
- )} - {this.state.connectors_ids.map(id => { - return this.renderLine(id, true); - })} -
-
- {Languages.t('components.connectorslistmanager.add_connectors')} -
-
- -
-
- this.filter(evt.target.value)} - /> -
-
- - {this.state.filtered.slice(0, 5).map(item => { - if (this.state.connectors_ids.indexOf(item.id) >= 0) { - return ''; - } - return this.renderLine(item, false); - })} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Draggable/Draggable.tsx b/twake/frontend/src/app/components/Draggable/Draggable.tsx deleted file mode 100755 index dfd648e126..0000000000 --- a/twake/frontend/src/app/components/Draggable/Draggable.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-use-before-define -import React from 'react'; -import './Draggable.scss'; -import DraggableManager from './DraggableManager.js'; -import classNames from 'classnames'; - -type PropsType = { [key: string]: any }; - -type StateType = { [key: string]: any }; - -export default class Draggable extends React.Component { - node: HTMLDivElement | null | undefined; - - render() { - return ( -
{ - this.node = node; - if (this.props.refDraggable) { - this.props.refDraggable(node); - } - }} - onClick={this.props.onClick} - onMouseDown={evt => { - !this.props?.deactivated && DraggableManager.start(evt, this.node, this); - }} - onMouseUp={evt => { - !this.props?.deactivated && DraggableManager.end(evt, this.node, this); - }} - onMouseOver={this.props.onMouseOver} - onMouseOut={this.props.onMouseOut} - onDoubleClick={this.props.onDoubleClick} - > - {this.props.children} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Draggable/DraggableBodyLayer.js b/twake/frontend/src/app/components/Draggable/DraggableBodyLayer.js deleted file mode 100755 index 8c9060886e..0000000000 --- a/twake/frontend/src/app/components/Draggable/DraggableBodyLayer.js +++ /dev/null @@ -1,23 +0,0 @@ -import React, { Component } from 'react'; - -import DraggableManager from './DraggableManager.js'; - -export default class DraggableBodyLayer extends React.Component { - constructor(props) { - super(); - this.state = { - draggable_manager: DraggableManager, - }; - this.draggable_body_dom = null; - DraggableManager.addListener(this); - } - componentDidMount() { - DraggableManager.registerContainer(this.draggable_body_dom); - } - componentWillUnmount() { - DraggableManager.removeListener(this); - } - render() { - return
(this.draggable_body_dom = node)} />; - } -} diff --git a/twake/frontend/src/app/components/Draggable/DraggableManager.js b/twake/frontend/src/app/components/Draggable/DraggableManager.js deleted file mode 100755 index 663794bee7..0000000000 --- a/twake/frontend/src/app/components/Draggable/DraggableManager.js +++ /dev/null @@ -1,238 +0,0 @@ -import React, { Component } from 'react'; - -import Observable from 'app/services/Depreciated/observable.js'; -import SelectionsManager from 'services/SelectionsManager/SelectionsManager.js'; - -class DraggableManager extends Observable { - constructor() { - super(); - this.setObservableName('draggable_manager'); - this.container = null; - - this.move = this.move.bind(this); - this.end = this.end.bind(this); - this.start = this.start.bind(this); - - this.drag = false; - this.clone_created = false; - this.drag_initial_point = []; - this.current_node_initial_position = []; - } - - registerContainer(container) { - this.container = container; - } - - setDropCallback(key, callback) { - this.callback_key = key; - this.callback = callback; - } - - removeDropCallback(key) { - if (this.callback_key == key) { - this.callback = false; - this.callback_key = null; - } - } - - start(evt, node, react_draggable) { - if (this.dragging) { - return; - } - - if (react_draggable.props.dragHandler) { - var onHandler = false; - var handlers = node.getElementsByClassName(react_draggable.props.dragHandler); - if (handlers.length > 0) { - Array.from(handlers).forEach(item => { - if (item == evt.target || item.contains(evt.target)) { - onHandler = true; - } - }); - } - - if (!onHandler) { - return; - } - } - - this.data = {}; - if (node) { - this.current_node = node; - } - if (react_draggable) { - this.current_react_draggable = react_draggable; - this.props = { - parentClassOnDrag: this.current_react_draggable.props.parentClassOnDrag, - minMove: this.current_react_draggable.props.minMove, - }; - this.data = this.current_react_draggable.props.data; - } - - this.selected_number = 1; - if (this.data.selection_type) { - this.selected_number = SelectionsManager.selected_per_type[this.data.selection_type]; - if (this.selected_number) { - this.selected_number = Object.keys(this.selected_number).length; - } - - if (!this.selected_number) { - this.selected_number = 1; - } - } - - evt.stopPropagation(); - evt.preventDefault(); - - document.addEventListener('mousemove', this.move); - document.addEventListener('mouseup', this.end); - var rect = window.getBoundingClientRect(this.current_node); - rect.x = rect.x || rect.left; - rect.y = rect.y || rect.top; - - this.clone_created = false; - this.drag_initial_point = [evt.clientX, evt.clientY]; - this.current_node_initial_position = [rect.left, rect.top, node.clientWidth, node.clientHeight]; - - this.drag = true; - if (this.current_react_draggable) this.current_react_draggable.setState({ drag: true }); - } - end(evt, node, react_draggable) { - if (this.dragging) { - evt.preventDefault(); - evt.stopPropagation(); - } - - this.current_react_draggable && this.current_react_draggable.setState({ hide_original: false }); - - if (!this.data) { - return; - } - - if (node) { - this.current_node = node; - } - if (react_draggable) { - this.current_react_draggable = react_draggable; - this.props = { - parentClassOnDrag: this.current_react_draggable.props.parentClassOnDrag, - minMove: this.current_react_draggable.props.minMove, - }; - } - - document.removeEventListener('mousemove', this.move); - document.removeEventListener('mouseup', this.end); - - document.body.classList.remove('dragging'); - document.body.classList.remove('drag_' + this.data.type); - this.drag = false; - this.dragging = false; - if (this.current_react_draggable) - this.current_react_draggable.setState({ drag: false, dragging: false }); - - var delete_delay = 0; - if (this.callback) { - this.callback(this.data); - } else { - if (this.clone) { - this.clone.style.transition = 'transform 0.2s'; - this.clone.style.transform = - 'translateX(' + - this.current_node_initial_position[0] + - 'px) translateY(' + - this.current_node_initial_position[1] + - 'px)'; - } - delete_delay = 200; - } - - setTimeout(() => { - if (this.clone) { - try { - this.container.removeChild(this.clone); - } catch (e) {} - } - if (this.current_react_draggable) - this.current_react_draggable.setState({ hide_original: false }); - if (this.props.parentClassOnDrag) { - this.props.parentClassOnDrag.split(' ').forEach(c => { - this.container.classList.remove(c); - }); - } - }, delete_delay); - - this.data = {}; - } - move(evt) { - if (!this.data) { - return; - } - - var deltaX = evt.clientX - this.drag_initial_point[0]; - var deltaY = evt.clientY - this.drag_initial_point[1]; - - if ( - !this.clone_created && - Math.max(Math.abs(deltaX), Math.abs(deltaY)) < (this.props.minMove || 10) - ) { - return; - } - - if (this.drag) { - if (!this.clone_created) { - var html = this.current_node.outerHTML; - var div = document.createElement('div'); - div.classList.add('draggable_clone'); - div.innerHTML = html.trim(); - div.firstChild.classList.remove('dragging_opacity'); - div.firstChild.classList.remove('fade_in'); - div.firstChild.classList.remove('is_selected'); - - div.style.width = this.current_node_initial_position[2] + 'px'; - div.style.height = this.current_node_initial_position[3] + 'px'; - - this.clone = div; - - if (this.selected_number > 1) { - var div_number = document.createElement('div'); - div_number.classList.add('draggable_number'); - div_number.innerHTML = this.selected_number; - this.clone.appendChild(div_number); - } - - this.container.appendChild(this.clone); - this.clone_created = true; - - if (this.props.parentClassOnDrag) { - this.props.parentClassOnDrag.split(' ').forEach(c => { - this.container.classList.add(c); - }); - } - - if ( - this.current_react_draggable && - this.current_react_draggable.props && - this.current_react_draggable.props.onDragStart - ) { - this.current_react_draggable.props.onDragStart(evt); - } - - this.dragging = true; - if (this.current_react_draggable) - this.current_react_draggable.setState({ dragging: true, hide_original: true }); - } - - document.body.classList.add('dragging'); - document.body.classList.add('drag_' + this.data.type); - this.clone.style.transform = - 'translateX(' + - (deltaX + this.current_node_initial_position[0]) + - 'px) translateY(' + - (deltaY + this.current_node_initial_position[1]) + - 'px)'; - } - } -} - -const service = new DraggableManager(); -export default service; diff --git a/twake/frontend/src/app/components/Draggable/DroppableZone.js b/twake/frontend/src/app/components/Draggable/DroppableZone.js deleted file mode 100755 index 88fcb9d748..0000000000 --- a/twake/frontend/src/app/components/Draggable/DroppableZone.js +++ /dev/null @@ -1,73 +0,0 @@ -import React, { Component } from 'react'; - -import DraggableManager from './DraggableManager.js'; -import Number from 'services/utils/Numbers'; -import './Draggable.scss'; - -export default class DroppableZone extends React.Component { - constructor(props) { - super(); - this.unique_drop_key = Number.unid(); - this.longOverTimeout = ''; - } - onDrop(data) { - if (!data) { - return; - } - if (this.props.types && data.type) { - if (this.props.types.indexOf(data.type) < 0) { - return; - } - } - if (this.props.onDrop) { - this.props.onDrop(data); - } - } - componentWillUnmount() { - DraggableManager.removeDropCallback(this.unique_drop_key); - clearTimeout(this.longOverTimeout); - } - onEnter() { - if (DraggableManager.drag) { - this.longOverTimeout = setTimeout(() => { - if (DraggableManager.drag) { - if (this.props.onClick && !this.props.disableLongOver) { - this.props.onClick(); - } - if (this.props.onLongOver) { - this.props.onLongOver(); - } - } - }, 1500); - DraggableManager.setDropCallback(this.unique_drop_key, d => this.onDrop(d)); - } - } - onLeave() { - DraggableManager.removeDropCallback(this.unique_drop_key); - clearTimeout(this.longOverTimeout); - } - render() { - return ( -
{ - if (!this.props.deactivated) { - this.onEnter(); - } - }} - onMouseLeave={() => { - if (!this.props.deactivated) { - this.onLeave(); - } - }} - > - {this.props.children} - {!this.props.children && !this.props.deactivated && ( -
{this.props.empty || ''}
- )} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Drive/Directory.js b/twake/frontend/src/app/components/Drive/Directory.js deleted file mode 100755 index 10cb13fca0..0000000000 --- a/twake/frontend/src/app/components/Drive/Directory.js +++ /dev/null @@ -1,87 +0,0 @@ -import React from 'react'; -import DriveElement from './DriveElement.js'; -import UIDirectory from './UI/Directory.js'; -import Loader from 'components/Loader/Loader.js'; - -import WorkspaceUserRights from 'services/workspaces/WorkspaceUserRights'; -import Draggable from 'components/Draggable/Draggable'; -import DroppableZone from 'components/Draggable/DroppableZone.js'; -import Languages from 'services/languages/languages'; -import './Drive.scss'; - -export default class Directory extends DriveElement { - constructor(props) { - super(); - this.props = props; - this.state = { - loading: true, - }; - } - componentDidMount() { - super.componentDidMount(); - if (this.state.loading) { - setTimeout(() => { - this.setState({ loading: false }); - }, 4000); - } - } - render() { - if (!this.state.element || !this.state.element.front_id) { - return ( -
- {this.state.loading && } - {!this.state.loading && ( - - {Languages.t( - 'components.drive.navigators.directory_not_found', - [], - 'Directory not found.', - )} - - )} -
- ); - } else { - this.state.loading = false; - } - - if (this.props.hide) { - return ''; - } - - return ( - this.dropFile(data)} - onLongOver={this.props.onClick} - className="directory_drop_zone" - > - (this.node = node)} - onClick={evt => { - this.clickElement(evt); - }} - onDoubleClick={this.props.onDoubleClick} - parentClassOnDrag="grid" - onDragStart={evt => { - this.dragElement(evt); - }} - minMove={10} - data={{ type: 'file', selection_type: this.props.selectionType, data: this.props.data }} - > - - - - ); - } -} diff --git a/twake/frontend/src/app/components/Drive/Drive.scss b/twake/frontend/src/app/components/Drive/Drive.scss deleted file mode 100755 index aa2fcb867a..0000000000 --- a/twake/frontend/src/app/components/Drive/Drive.scss +++ /dev/null @@ -1,522 +0,0 @@ -/* Drive */ - -.directory, -.file { - .file_loader { - width: 32px; - height: 32px; - display: inline-block; - margin: auto; - } - .options { - padding-left: 5px; - display: none; - } - - &:hover { - .options { - display: block; - } - } -} - -.directory_drop_zone { - display: inline-block; -} -.directory { - background: #fff; - border: 1px solid var(--grey-background); - height: 50px; - box-sizing: border-box; - display: inline-flex; - flex-direction: row; - line-height: 32px; - margin-right: 16px; - margin-bottom: 16px; - border-radius: var(--border-radius-base); - font-size: 13px; - vertical-align: middle; - width: 200px; - padding: 8px; - font-weight: 500; - padding-right: 12px; - cursor: pointer; - - .text { - font-size: 12px; - font-weight: bold; - } - - &:hover:not(.notInDrive) { - box-shadow: 4px 4px 16px 0 #00000022; - border-color: #fff; - } - - .options { - .m-icon-small { - font-size: 20px !important; - } - } - - .app_icon { - width: 20px; - background-size: contain; - background-position: center; - background-repeat: no-repeat; - height: 20px; - margin-top: 2px; - } - - .icon { - font-size: 14px; - padding-right: 8px; - margin-left: 6px; - padding-top: 4px; - - .m-icon-small { - color: var(--warning); - font-size: 20px !important; - } - - i.icon-fontastic { - position: relative; - top: 8px; - } - - .icon { - height: 30px; - background-size: 16px auto; - background-position: center left; - background-repeat: no-repeat; - } - } -} - -.file { - overflow: hidden; - border: 1px solid var(--grey-background); - background: #fff; - height: 180px; - width: 216px; - box-sizing: border-box; - display: inline-flex; - flex-direction: column; - line-height: 30px; - margin-right: 16px; - margin-bottom: 16px; - border-radius: var(--border-radius-base); - font-size: 13px; - vertical-align: middle; - position: relative; - cursor: pointer; - - &:hover:not(.notInDrive) { - box-shadow: 4px 4px 16px 0 #00000022; - border-color: #fff; - } - - .options { - .m-icon-small { - font-size: 20px !important; - } - } - - &.mini { - height: 32px; - - .data { - border-top: none; - .no-grid { - display: none; - } - } - - .preview { - height: 32px; - background: #fff !important; - - &:after { - content: none; - } - } - } - - .preview { - width: 216px; - background-size: contain; - background-repeat: no-repeat; - background-position: center; - background-color: #f5f5f7; - flex: 1; - - .tags_list { - position: absolute; - top: 4px; - padding-left: 8px; - line-height: 30px; - } - - &.no_preview { - background-color: #f5f5f7; - background-repeat: no-repeat; - background-size: 64px; - } - - /*&:after { - content: ""; - position: absolute; - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.05) 70%, rgba(0,0,0,0.5) 100%); - }*/ - } - - .data { - display: flex; - flex-direction: row; - padding-left: 8px; - padding-right: 8px; - bottom: 0px; - color: var(--black); - height: 32px; - font-weight: 500; - width: 100%; - box-sizing: border-box; - border-top: 1px solid var(--grey-background); - - .icon { - height: 20px; - width: 20px; - box-sizing: border-box; - border-radius: var(--border-radius-base); - margin-right: 6px; - margin-left: -3px; - margin-top: 5px; - color: #fff; - text-align: center; - background-size: 70%; - background-repeat: no-repeat; - background-position: center; - - i.icon-fontastic { - position: relative; - top: 4px; - } - } - } -} - -.draggable_clone { - .file, - .directory { - opacity: 1; - box-shadow: 4px 4px 16px 0 #00000022; - border-color: #fff; - } -} - -.dragging.drag_file .drive_multiselector { - .file.is_selected, - .directory.is_selected { - opacity: 0; - transition: opacity 0.2s; - } -} - -.file, -.directory { - transition: opacity 0s; - - &.notInDrive { - margin-bottom: 0px; - } - - &.dragging_opacity { - opacity: 0; - } - - &.is_selected { - background: var(--primary); - color: #fff; - box-shadow: none; - - .file_type_icon svg, - .file_type_icon svg * { - fill: #fff; - } - - &:hover:not(.notInDrive), - .data { - background-color: var(--primary); - color: #fff; - } - } - - .text { - flex: 1; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .created-by, - .last-modified { - width: 200px; - } - - .size { - text-align: right; - width: 70px; - } - - .last-modified { - text-align: right; - width: 120px; - } - - .detail_preview_parent { - width: 32px; - margin-left: 12px; - - .detail_preview { - width: 32px; - height: 32px; - border-radius: var(--border-radius-base); - background-position: center; - background-repeat: no-repeat; - background-size: cover; - background-color: var(--primary-background); - - &.no_preview { - background-size: 60%; - } - } - } -} - -.drive_view.list { - .directory_drop_zone { - display: inherit; - } -} - -.drive_view.list .directory, -.drive_view.list .file { - margin-right: 0px; - margin-bottom: 0px; - border: 0; - border-bottom: 1px solid var(--grey-background); - border-top: 1px solid var(--grey-background); - border-radius: 2px; - width: 100%; - height: 64px; - padding-top: 16px; - color: var(--black); - margin-top: -1px; - padding-right: 12px; - - &.exit-active, - &.enter-active { - margin-top: -1px !important; - } - - .data { - border-top: 0px; - bottom: -1px; - } - - .text { - font-size: 14px; - } - - .options { - display: block; - } - - &:hover:not(.notInDrive):not(.is_selected) { - box-shadow: none; - background: var(--primary-background); - } - - &.is_selected { - background: var(--primary); - color: #fff; - box-shadow: none; - } -} - -.drive_view.list .file .preview { - display: none; -} - -.drive_view.list { - .rounded-btn { - margin-top: 10px; - } -} - -.drive_view.grid { - .is_selected.file { - background: var(--primary); - color: #fff; - box-shadow: none; - } -} - -.drive_view.grid .no-grid { - display: none; -} -.drive_view.list .no-list { - display: none; -} - -.file_type_icon { - line-height: 38px; - width: 24px; - - svg, - svg * { - fill: var(--primary); - } - - &.link { - background-image: url('./Icons/link.svg'); - } - - &.code { - background-image: url('./Icons/code.svg'); - } - - &.document { - background-image: url('./Icons/document.svg'); - } - - &.image { - background-image: url('./Icons/image.svg'); - } - - &.pdf { - background-image: url('./Icons/pdf.svg'); - } - - &.slides { - background-image: url('./Icons/slides.svg'); - } - - &.sound { - background-image: url('./Icons/sound.svg'); - } - - &.spreadsheet { - background-image: url('./Icons/spreadsheet.svg'); - } - - &.svg { - background-image: url('./Icons/svg.svg'); - } - - &.video { - background-image: url('./Icons/video.svg'); - } - - &.archive { - background-image: url('./Icons/archive.svg'); - } - - &.other { - background-image: url('./Icons/file.svg'); - } -} - -.drive_view.list .file_type_icon { - line-height: 38px; - width: 34px; - text-align: center; -} - -/* version details */ -.versionDetails { - min-height: 250px; - - .text.no-more { - text-align: center; - width: 100%; - opacity: 0.5; - margin-top: 32px; - margin-bottom: 32px; - } - - .version { - display: flex; - padding: 24px 0px; - border-bottom: solid 1px var(--grey-background); - .titleVersionDetails { - font-size: 24px; - color: var(--black); - font-weight: bold; - margin-bottom: 24px; - } - .info { - flex: 0.5; - margin-bottom: 8px; - .versionTitle { - font-size: 14px; - font-weight: bold; - color: var(--black); - } - .versionDate { - font-size: 14px; - color: var(--black); - } - } - .name { - flex: 0.5; - font-size: 14px; - line-height: 24px; - color: var(--black); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - .more { - } - } -} -.footerVersionDetails { - display: flex; - .addVersion { - flex: 1; - .addVersionButton { - width: 100%; - height: 24px; - line-height: 24px; - } - .addVersionButton:hover { - cursor: pointer; - opacity: 0.8; - } - .icon { - display: inline-block; - width: 24px; - height: 24px; - .iconWithBackground { - width: 24px; - height: 24px; - display: inline-block; - background-color: var(--grey-background); - border-radius: var(--border-radius-base); - } - } - .footerTitle { - margin-left: 8px; - display: inline-block; - font-size: 14px; - font-weight: bold; - color: var(--black); - .addVersionButton:hover { - cursor: pointer; - opacity: 0.8; - } - } - } -} diff --git a/twake/frontend/src/app/components/Drive/DriveElement.js b/twake/frontend/src/app/components/Drive/DriveElement.js deleted file mode 100755 index 117769ae96..0000000000 --- a/twake/frontend/src/app/components/Drive/DriveElement.js +++ /dev/null @@ -1,643 +0,0 @@ -import React, { useState } from 'react'; - -import SelectionsManager from 'services/SelectionsManager/SelectionsManager.js'; -import DriveService from 'services/Apps/Drive/Drive.js'; -import AlertManager from 'services/AlertManager/AlertManager'; -import MenuManager from 'app/components/Menus/MenusManager.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import FilePicker from 'components/Drive/FilePicker/FilePicker.js'; -import Button from 'components/Buttons/Button.js'; -import Input from 'components/Inputs/Input.js'; -import VersionDetails from './VersionDetails.js'; -import WorkspacesApps from 'services/workspaces/workspaces_apps.js'; -import InputWithClipBoard from 'components/InputWithClipBoard/InputWithClipBoard.js'; -import WorkspaceUserRights from 'services/workspaces/WorkspaceUserRights'; -import MediumPopupManager from 'app/components/Modal/ModalManager'; -import Languages from 'services/languages/languages'; -import TagPicker from 'components/TagPicker/TagPicker.js'; -import RouterServices from 'services/RouterService'; -import { getAsFrontUrl } from 'app/services/utils/URLUtils'; -import FeatureTogglesService, { FeatureNames } from 'app/services/FeatureTogglesService'; -import ModalManager from 'app/components/Modal/ModalManager'; -import InitService from 'app/services/InitService'; -import LockedOnlyOfficePopup from 'app/components/LockedFeaturesComponents/LockedOnlyOfficePopup/LockedOnlyOfficePopup'; - -const RenameInput = props => { - const [value, setValue] = useState(props.value); - return ( -
-
- { - if ((value || '').trim().length > 0) { - props.rename(value); - } - }} - className="full_width bottom-margin" - onEchap={() => { - MenuManager.closeMenu(); - }} - autoFocus - value={value} - onChange={evt => setValue(evt.target.value)} - /> -
-
-
-
- ); -}; - -const PublicSharing = props => { - Collections.get('drive').useListener(useState); - const element = Collections.get('drive').find(props.id); - if (!element) { - return
; - } - const sharedUrl = RouterServices.generateRouteFromState({ - workspaceId: element.workspace_id, - documentId: element.id, - appName: 'drive', - shared: true, - token: (element.acces_info || {}).token, - }); - return ( -
- {(element.acces_info || {}).token && ( -
- -
-
-
- )} - {!(element.acces_info || {}).token && ( -
-
- )} -
- ); -}; - -export default class DriveElement extends React.Component { - constructor(props) { - super(); - this.state = { - selections_manager: SelectionsManager, - }; - SelectionsManager.addListener(this); - - this.driveCollectionKey = ''; - - this.driveSelectorOver = this.driveSelectorOver.bind(this); - this.driveSelectorOut = this.driveSelectorOut.bind(this); - Collections.get('drive').addListener(this); - } - componentWillUnmount() { - SelectionsManager.removeListener(this); - Collections.get('drive').removeListener(this); - if (this.node) { - this.node.removeEventListener('drive_selector_over', this.driveSelectorOver); - this.node.removeEventListener('drive_selector_out', this.driveSelectorOut); - } - - if (this.driveCollectionKey && this.driveCollectionKey != this.props.driveCollectionKey) { - Collections.get('drive').removeSource(this.driveCollectionKey); - } - } - componentWillMount() { - if (this.props && this.props.data && this.props.data.front_id) { - Collections.get('drive').listenOnly(this, [this.props.data.front_id]); - } - - this.state.element = DriveService.find( - Workspaces.currentWorkspaceId, - this.props.data.id, - el => { - this.setState({ element: el }); - }, - ); - this.updateMenu(); - } - componentDidMount() { - if (this.node) { - this.node.addEventListener('drive_selector_over', this.driveSelectorOver); - this.node.addEventListener('drive_selector_out', this.driveSelectorOut); - this.node.setAttribute('drive_selector_unid', this.state.element.id); - } - - if (this.props && this.props.data && this.props.data.id) { - SelectionsManager.listenOnly(this, [this.props.data.id]); - } - } - driveSelectorOut() { - if (this.state.selected) this.setState({ selected: false }); - } - driveSelectorOver() { - if (!this.state.selected) this.setState({ selected: true }); - } - - dropFile(data, directory) { - var destination = directory || this.props.data; - - var objects = data.data.id; - if (data.selection_type) { - var selected = Object.keys(SelectionsManager.selected_per_type[data.selection_type] || {}); - if (selected && selected.length > 1) { - var objects = selected; - } - } - - DriveService.moveFile( - objects, - destination, - this.props.driveCollectionKey || this.driveCollectionKey, - ); - } - - dragElement(evt) { - SelectionsManager.setType(this.props.selectionType); - if ( - !evt.shiftKey && - !SelectionsManager.selected_per_type[this.props.selectionType][this.state.element.id] - ) { - SelectionsManager.unselectAll(); - } - SelectionsManager.select(this.state.element.id); - } - - clickElement(evt, previewonly = false) { - evt.stopPropagation(); - evt.preventDefault(); - - if (this.props.notInDrive) { - if (this.props.onClick) { - this.props.onClick(); - } else { - DriveService.viewDocument(this.state.element, previewonly); - } - } else { - SelectionsManager.setType(this.props.selectionType); - if (!evt.shiftKey) { - if (this.props.onClick) { - this.props.onClick(); - } else { - DriveService.viewDocument(this.state.element, previewonly); - } - - var oldStatus = - SelectionsManager.selected_per_type[this.props.selectionType][this.state.element.id]; - SelectionsManager.unselectAll(); - if (oldStatus) { - SelectionsManager.unselect(this.state.element.id); - } else { - SelectionsManager.select(this.state.element.id); - } - } else { - SelectionsManager.toggle(this.state.element.id); - } - } - } - componentWillUpdate(nextProps, nextState) { - nextState.element = - Collections.get('drive').find(this.props.data.id) || - DriveService.find(Workspaces.currentWorkspaceId, this.props.data.id, el => { - this.setState({ element: el }); - }); - this.state.element = nextState.element; - - if ( - this.state.element && - SelectionsManager.selected_per_type[nextProps.selectionType] && - SelectionsManager.selected_per_type[nextProps.selectionType][this.state.element.id] != - this.old_selection_state - ) { - nextState.selected = - SelectionsManager.selected_per_type[nextProps.selectionType][nextProps.data.id]; - this.old_selection_state = nextState.selected; - } - - if (this.state.element && !this.props.driveCollectionKey) { - this.channel = 'standalone_drive_collection_' + this.state.element.parent_id; - var parent_id = this.state.element.parent_id; - if (this.state.element.parent_id == 'detached') { - parent_id += '_' + this.state.element.workspace_id; - } - var old_collection_key = this.driveCollectionKey; - this.driveCollectionKey = DriveService.addSourceIfNotExist( - Workspaces.currentWorkspaceId, - this.channel, - parent_id, - 'standalone', - ); - if (old_collection_key && old_collection_key != this.driveCollectionKey) { - Collections.get('drive').removeSource(old_collection_key); - } - } - - this.updateMenu(); - - return true; - } - - moveTo(new_parent) { - DriveService.moveFile( - [this.state.element.id], - new_parent, - this.props.driveCollectionKey || this.driveCollectionKey, - ); - } - - rename(new_name) { - if (!this.state.element.is_directory) { - new_name = new_name + '.' + this.state.element.extension; - } - this.state.element.name = new_name || this.state.element.name; - new_name = undefined; - MenuManager.closeMenu(); - DriveService.save(this.state.element, this.props.driveCollectionKey || this.driveCollectionKey); - } - - updateMenu() { - if (!this.state.element) { - this.common_menu = []; - return; - } - - this.common_menu = []; - - //-- All files - if (!this.state.element.is_directory) { - this.common_menu = [ - { - type: 'menu', - text: Languages.t('components.drive.elements.see', [], 'Voir'), - onClick: () => { - DriveService.viewDocument(this.state.element); - }, - }, - ]; - - var candidates = DriveService.getEditorsCandidates(this.state.element); - var preview_candidate = candidates.editor_candidate || []; - var editor_candidate = candidates.preview_candidate || []; - - if (editor_candidate.length > 0 && editor_candidate[0].app) { - this.common_menu.push({ - type: 'menu', - text: Languages.t( - 'scenes.apps.drive.viewer.edit_with_button', - [editor_candidate[0].app.identity?.name], - 'Editer avec $1', - ), - onClick: () => { - if (FeatureTogglesService.isActiveFeatureName(FeatureNames.EDIT_FILES)) { - var app = editor_candidate[0]; - if (app.url && app.is_url_file) { - window.open(app.url); - } - var app = app.app; - DriveService.getFileUrlForEdition( - app.display?.twake?.files?.editor?.edition_url, - app, - this.state.element.id, - url => { - window.open(url); - }, - ); - } else { - ModalManager.open( - , - { - position: 'center', - size: { width: '600px' }, - }, - false, - ); - } - }, - }); - } - } - - this.common_menu.push({ - type: 'menu', - text: - this.state.element.url && this.state.element.extension == 'url' - ? Languages.t('scenes.apps.drive.open_link', [], 'Open link') - : Languages.t('scenes.apps.drive.download_button', [], 'Télécharger'), - onClick: () => { - var link = DriveService.getLink(this.state.element, undefined, 1); - if (this.state.element.url) { - window.open(link, '_blank'); - } else { - window.open(link); - } - }, - }); - - if (!WorkspaceUserRights.isNotConnected()) { - //-- All files - if (this.state.element.detached) { - this.common_menu.push({ - type: 'menu', - text: Languages.t('scenes.apps.drive.move_text2', [], 'Déplacer'), - submenu_replace: true, - submenu: [ - { - type: 'react-element', - reactElement: () => ( - this.moveTo(res)} - initialDirectory={{ id: '' }} - /> - ), - }, - ], - }); - } - - if (!this.props.notInDrive && !this.state.element.detached) { - if (this.common_menu.length > 0) { - this.common_menu.push({ type: 'separator' }); - } - - if (!this.state.element.detached && this.state.element.parent_id) { - this.common_menu = this.common_menu.concat([ - { - type: 'menu', - text: Languages.t('scenes.app.mainview.tabs.rename', [], 'Renommer'), - submenu_replace: true, - submenu: [ - { - type: 'title', - text: Languages.t('scenes.app.mainview.tabs.rename', [], 'Renommer'), - }, - { - type: 'text', - text: - Languages.t('components.drive.elements.current_name', [], 'Nom actuel : ') + - this.state.element.name, - }, - { - type: 'react-element', - reactElement: () => ( - { - this.rename(name); - }} - value={ - this.state.element.is_directory - ? this.state.element.name - : this.state.element.name.replace(/\.[^.]*$/, '') - } - /> - ), - }, - ], - }, - ]); - } - - if (!this.state.element.trash) { - this.common_menu = this.common_menu.concat([ - { - type: 'menu', - text: Languages.t('scenes.apps.drive.right_preview.public', [], 'Accès public...'), - submenu_replace: true, - submenu: [ - { - type: 'title', - text: Languages.t( - 'scenes.apps.drive.right_preview.public_link', - [], - "Lien d'accès public", - ), - }, - { - //TODO menu react-element to refactor - type: 'react-element', - reactElement: () => ( - - ), - }, - ], - }, - ]); - - if (!(this.state.element.application_id && this.state.element.is_directory)) { - this.common_menu.push({ - type: 'menu', - text: Languages.t('scenes.apps.drive.move_text', [], 'Déplacer'), - submenu_replace: true, - submenu: [ - { - type: 'react-element', - reactElement: () => ( - this.moveTo(res)} - initialDirectory={{ id: this.state.element.parent_id }} - /> - ), - }, - ], - }); - } - - if (WorkspaceUserRights.hasWorkspacePrivilege()) { - if (this.state.element.application_id && this.state.element.is_directory) { - this.common_menu.push({ - type: 'menu', - text: Languages.t( - 'components.drive.elements.configurate_mod', - [], - 'Configurer le module...', - ), - onClick: () => { - var data = { - drive_element: this.state.element, - }; - WorkspacesApps.notifyApp( - this.state.element.application_id, - 'configuration', - 'drive', - data, - ); - }, - }); - } - } - - if (!this.state.element.is_directory && !this.state.element.url) { - var versions_indicator = ''; - if ((this.state.element.versions || {}).length > 1) { - versions_indicator = ' (' + (this.state.element.versions || {}).length + ')'; - } - this.common_menu.push( - { - type: 'menu', - text: - Languages.t( - 'components.drive.elements.manage_version', - [], - 'Gérer les versions', - ) + - versions_indicator + - '...', - onClick: () => { - MediumPopupManager.open(, { - size: { width: 600 }, - }); - }, - }, - { - type: 'menu', - text: Languages.t( - 'scenes.apps.drive.navigators.navigator_labels.title', - [], - 'Labels', - ), - submenu_replace: true, - submenu: [ - { - type: 'title', - text: Languages.t( - 'scenes.apps.drive.navigators.navigator_labels.title', - [], - 'Labels', - ), - }, - { - type: 'react-element', - reactElement: level => ( -
- { - this.state.element.tags = values; - MenuManager.closeMenu(); - DriveService.save( - this.state.element, - this.props.driveCollectionKey || this.driveCollectionKey, - ); - }} - /> -
- ), - }, - ], - }, - ); - } - - if (this.props.attachmentMenu) { - this.common_menu.push(this.props.attachment_menu); - } - - this.common_menu.push({ type: 'separator' }); - - this.common_menu.push({ - type: 'menu', - text: Languages.t( - 'scenes.apps.drive.right_preview.operations_delete', - [], - 'Mettre à la corbeille', - ), - className: 'error', - onClick: () => { - DriveService.remove( - [this.props.data], - this.props.driveCollectionKey || this.driveCollectionKey, - ); - }, - }); - } else { - this.common_menu.push({ - type: 'menu', - text: Languages.t( - 'scenes.apps.drive.right_preview.operations_restore', - [], - 'Restaurer', - ), - onClick: () => { - DriveService.restore( - [this.props.data], - this.props.driveCollectionKey || this.driveCollectionKey, - ); - }, - }); - this.common_menu.push({ - type: 'menu', - text: Languages.t( - 'scenes.apps.drive.remove_definitely_menu', - [], - 'Supprimer définitivement', - ), - className: 'error', - onClick: () => { - AlertManager.confirm(() => { - DriveService.removeDefinitively( - [this.props.data], - this.props.driveCollectionKey || this.driveCollectionKey, - ); - }); - }, - }); - } - } - - if (this.props.additionalMenu && this.props.additionalMenu.length > 0) { - this.common_menu.push({ type: 'separator' }); - this.common_menu = this.common_menu.concat(this.props.additionalMenu); - } - } - } -} diff --git a/twake/frontend/src/app/components/Drive/DriveMultiSelector.js b/twake/frontend/src/app/components/Drive/DriveMultiSelector.js deleted file mode 100755 index 1358737bd6..0000000000 --- a/twake/frontend/src/app/components/Drive/DriveMultiSelector.js +++ /dev/null @@ -1,276 +0,0 @@ -import React, { Component } from 'react'; - -import './DriveMultiSelector.scss'; -import SelectionsManager from 'services/SelectionsManager/SelectionsManager.js'; -import './Drive.scss'; - -export default class DriveMultiSelector extends React.Component { - constructor(props) { - super(); - this.state = { - start_drag: false, - dragging: true, - }; - this.move = this.move.bind(this); - this.end = this.end.bind(this); - this.start = this.start.bind(this); - this.pause = this.pause.bind(this); - this.unpause = this.unpause.bind(this); - - this.currentSelection = {}; - this.currentSelectionCount = 0; - - this.noMovementRefreshAnyway = setTimeout(''); - } - componentDidMount() { - this.scroller_container = this.props.scroller; - } - componentWillUnmount() { - clearInterval(this.noMovementRefreshAnyway); - - this.container.removeEventListener('mouseleave', this.pause); - this.container.removeEventListener('mouseenter', this.unpause); - document.removeEventListener('mousemove', this.move); - document.removeEventListener('mouseup', this.end); - document.body.classList.remove('no_select'); - } - pause() { - clearInterval(this.noMovementRefreshAnyway); - - this.setState({ dragging: false }); - } - unpause() { - this.setState({ dragging: true }); - } - end(evt) { - clearInterval(this.noMovementRefreshAnyway); - - this.setState({ start_drag: false }); - - document.removeEventListener('mousemove', this.move); - document.removeEventListener('mouseup', this.end); - this.container.removeEventListener('mouseleave', this.pause); - this.container.removeEventListener('mouseenter', this.unpause); - - document.body.classList.remove('no_select'); - - if (!this.did_drag) { - if (!evt.shiftKey && !this.did_start_drag == 0) { - SelectionsManager.unselectAll(); - } - this.did_start_drag = false; - return; - } - this.did_drag = false; - - Object.keys(this.currentSelection).forEach(id => { - if (this.currentSelection[id]) { - SelectionsManager.select(id); - } else { - SelectionsManager.unselect(id); - } - }); - this.did_start_drag = false; - - this.noMovementRefreshAnyway = setTimeout(() => { - this.state.left = 0; - this.state.right = 0; - this.state.width = 0; - this.state.height = 0; - this.setState({}); - }, 500); - } - start(evt) { - this.did_drag = false; - this.did_start_drag = true; - - this.element_position_cache = {}; - - SelectionsManager.setType(this.props.selectionType); - - clearInterval(this.noMovementRefreshAnyway); - this.currentSelection = {}; - - this.state.start_drag = true; - this.state.dragging = true; - var rect = window.getBoundingClientRect(this.container); - rect.x = rect.x || rect.left; - rect.y = rect.y || rect.top; - - this.drag_add = evt.nativeEvent.shiftKey; - this.drag_start = [ - evt.clientX - rect.left, - evt.clientY - rect.top, - this.container.scrollLeft, - this.container.scrollTop, - ]; - - document.addEventListener('mousemove', this.move); - document.addEventListener('mouseup', this.end); - this.container.addEventListener('mouseleave', this.pause); - this.container.addEventListener('mouseenter', this.unpause); - - document.body.classList.add('no_select'); - - var rect = {}; - rect.width = 0; - rect.height = 0; - rect.left = evt.clientX; - rect.top = evt.clientY; - this.autoSelect(rect); - } - move(evt) { - clearInterval(this.noMovementRefreshAnyway); - var rect = window.getBoundingClientRect(this.container); - rect.x = rect.x || rect.left; - rect.y = rect.y || rect.top; - - if (this.state.start_drag && this.state.dragging) { - this.did_drag = true; - - var pos = [evt.clientX - rect.left, evt.clientY - rect.top]; - - pos[0] = Math.min(pos[0], rect.width - 5); - pos[0] = Math.max(pos[0], 5); - - pos[1] = Math.min(pos[1], rect.height - 5); - pos[1] = Math.max(pos[1], 5); - - var w = this.drag_start[0] + this.drag_start[2] - (pos[0] + this.container.scrollLeft); - var h = this.drag_start[1] + this.drag_start[3] - (pos[1] + this.container.scrollTop); - var winv = w > 0; - var hinv = h > 0; - var selectorRect = { - width: Math.abs(w), - height: Math.abs(h), - left: this.drag_start[0] + this.drag_start[2] - Math.abs(winv ? w : 0), - top: this.drag_start[1] + this.drag_start[3] - Math.abs(hinv ? h : 0), - }; - this.setState(selectorRect); - - var rect = window.getBoundingClientRect(this.selector); - rect.x = rect.x || rect.left; - rect.y = rect.y || rect.top; - this.autoSelect(rect); - } - - var pos = [evt.clientX, evt.clientY]; - - if ( - rect.height + rect.top < pos[1] || - rect.top > pos[1] || - rect.width + rect.left < pos[0] || - rect.left > pos[0] - ) { - var newScrollTop = - this.container.scrollTop + - (pos[1] - ((pos[1] > rect.height + rect.top ? rect.height : 0) + rect.top)) / 10; - var newScrollLeft = - this.container.scrollLeft + - (pos[0] - ((pos[0] > rect.width + rect.top ? rect.width : 0) + rect.left)) / 10; - - if (this.container.scrollTop != newScrollTop || this.container.scrollLeft != newScrollLeft) { - this.container.scrollTop = newScrollTop; - this.container.scrollLeft = newScrollLeft; - this.state.dragging = true; - - this.noMovementRefreshAnyway = setTimeout(() => { - this.move({ - clientX: evt.clientX, - clientY: evt.clientY, - }); - }, 50); - } else { - this.state.dragging = false; - } - } - } - autoSelect(rect) { - this.currentSelectionCount = 0; - var scroll_top = this.container.scrollTop; - if (this.old_scroll_top != scroll_top) { - this.element_position_cache = {}; - } - this.old_scroll_top = scroll_top; - - Array.from(this.container.getElementsByClassName('js-drive-multi-selector-selectable')).forEach( - element => { - var element_id = element.getAttribute('drive_selector_unid'); - - var selected = SelectionsManager.selected_per_type[this.props.selectionType][element_id]; - var current_selection = this.currentSelection[element_id]; - - var over = false; - var elementRect = {}; - - if (this.element_position_cache[element_id]) { - elementRect = JSON.parse(JSON.stringify(this.element_position_cache[element_id])); - } else { - var er = window.getBoundingClientRect(element); - er.x = er.x || er.left; - er.y = er.y || er.top; - elementRect = JSON.parse(JSON.stringify(er)); - this.element_position_cache[element_id] = elementRect; - } - - if ( - !( - rect.left > elementRect.left + elementRect.width || - elementRect.left > rect.left + rect.width || - rect.top > elementRect.top + elementRect.height || - elementRect.top > rect.top + rect.height - ) - ) { - over = true; - } - - if ( - (over && this.drag_add && selected) || - (!over && this.drag_add && !selected) || - (!over && !this.drag_add) - ) { - element.dispatchEvent(new Event('drive_selector_out')); - this.currentSelection[element_id] = false; - } - if ( - (over && this.drag_add && !selected) || - (over && !this.drag_add) || - (!over && this.drag_add && selected) - ) { - element.dispatchEvent(new Event('drive_selector_over')); - this.currentSelection[element_id] = true; - this.currentSelectionCount++; - } - }, - ); - } - render() { - return ( -
{ - this.start(evt); - }} - onMouseUp={evt => { - this.end(evt); - }} - ref={node => (this.container = node)} - style={this.props.style || {}} - className={'drive_multiselector'} - > -
(this.selector = node)} - className={ - 'selectionRect ' + (this.state.start_drag && this.state.dragging ? 'visible ' : '') - } - style={{ - width: this.state.width, - height: this.state.height, - left: this.state.left, - top: this.state.top, - }} - /> - {this.props.children} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Drive/File.tsx b/twake/frontend/src/app/components/Drive/File.tsx deleted file mode 100755 index ae7abe4ceb..0000000000 --- a/twake/frontend/src/app/components/Drive/File.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React from 'react'; -import Draggable from 'components/Draggable/Draggable'; -import DriveElement from './DriveElement.js'; -import './Drive.scss'; -import UIFile from './UI/File.js'; -import Loader from 'components/Loader/Loader.js'; -import WorkspaceUserRights from 'services/workspaces/WorkspaceUserRights'; -import Languages from 'services/languages/languages'; - -type PropsType = { [key: string]: any }; - -type StateType = any; - -type NodeType = any; - -export default class File extends DriveElement { - node: NodeType; - state: StateType; - constructor(props: PropsType) { - super(); - this.state = { - loading: true, - }; - } - componentDidMount() { - super.componentDidMount(); - if (this.state.loading) { - setTimeout(() => { - this.setState({ loading: false }); - }, 4000); - } - } - render() { - if (!this.state.element || !this.state.element.front_id) { - return ( -
- {this.state.loading && } - {!this.state.loading && ( - - {Languages.t('scenes.apps.drive.preview_bloc.error_file', [], 'File not found.')} - - )} -
- ); - } else { - this.state.loading = false; - } - - if (this.props.hide) { - return ''; - } - - var mini = (!this.state.element.has_preview && this.props.notInDrive) || this.props.mini; - return ( - (this.node = node)} - onClick={(evt: any) => this.clickElement(evt, this.props.previewonly)} - onDoubleClick={this.props.onDoubleClick} - parentClassOnDrag="drive_view list" - onDragStart={(evt: any) => { - this.dragElement(evt); - }} - minMove={10} - data={{ type: 'file', selection_type: this.props.selectionType, data: this.props.data }} - deactivated={WorkspaceUserRights.isNotConnected() || this.props.notInDrive} - > - { - e.preventDefault(); - e.stopPropagation(); - this.props.removeOnClick(); - }} - /> - - ); - } -} diff --git a/twake/frontend/src/app/components/Drive/FilePicker/FilePicker.js b/twake/frontend/src/app/components/Drive/FilePicker/FilePicker.js deleted file mode 100755 index 6fe4a9c472..0000000000 --- a/twake/frontend/src/app/components/Drive/FilePicker/FilePicker.js +++ /dev/null @@ -1,216 +0,0 @@ -import React, { Component } from 'react'; - -import DriveService from 'services/Apps/Drive/Drive.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Languages from 'services/languages/languages'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import UIFile from '../UI/File.js'; -import UIDirectory from '../UI/Directory.js'; -import LeftIcon from '@material-ui/icons/KeyboardArrowLeftOutlined'; -import NewFolderIcon from '@material-ui/icons/CreateNewFolderOutlined'; -import Menu from 'components/Menus/Menu.js'; -import Button from 'components/Buttons/Button.js'; -import Input from 'components/Inputs/Input.js'; -import ChannelsService from 'services/channels/channels.js'; -import './FilePicker.scss'; - -export default class FilePicker extends React.Component { - constructor(props) { - super(); - this.drive_channel = 'file_picker_' + Workspaces.currentWorkspaceId; - this.drive_collection_key = this.drive_channel; - - this.state = { - i18n: Languages, - drive_repository: Collections.get('drive'), - app_drive_service: DriveService, - current_selection: {}, - creating_folder: false, - }; - - Languages.addListener(this); - Collections.get('drive').addListener(this); - DriveService.addListener(this); - } - componentWillUnmount() { - Languages.removeListener(this); - Collections.get('drive').removeListener(this); - DriveService.removeListener(this); - - if (this.drive_channel) { - Collections.get('drive').removeSource( - this.state.app_drive_service.current_collection_key_channels[this.drive_channel], - ); - } - } - componentDidMount() { - this.changeCurrentDirectory({ id: (this.props.initialDirectory || {}).id || '' }); - } - clickOnFile(file) { - if (this.props.mode == 'select_file') { - this.setState({ current_selection: file }); - } - } - changeCurrentDirectory(directory) { - if (this.props.mode == 'select_file') { - this.setState({ current_selection: {} }); - } - if (this.props.mode == 'select_location') { - this.setState({ current_selection: directory }); - } - DriveService.changeCurrentDirectory(this.drive_channel, directory); - } - submit() { - var result = null; - if (this.props.mode == 'select_file') { - result = this.state.current_selection; - } - if (this.props.mode == 'select_location') { - result = this.state.app_drive_service.current_directory_channels[this.drive_channel] || {}; - } - Menu.closeAll(); - if (this.props.onChoose) this.props.onChoose(result); - } - render() { - var workspace_id = Workspaces.currentWorkspaceId; - var directory = - this.state.app_drive_service.current_directory_channels[this.drive_channel] || {}; - var directory_id = directory.id; - - var filter_dir = { - workspace_id: workspace_id, - parent_id: directory_id, - is_directory: true, - trash: false, - }; - var directories = this.state.drive_repository - .findBy(filter_dir) - .sort((a, b) => (a.name || '').localeCompare(b.name || '')); - - var filter_files = { - workspace_id: workspace_id, - parent_id: directory_id, - is_directory: false, - trash: false, - }; - var files = this.state.drive_repository - .findBy(filter_files) - .sort((a, b) => (a.name || '').localeCompare(b.name || '')); - - var allow_go_parent = true; - var drive_channel = ChannelsService.getChannelForApp( - (Collections.get('applications').findBy({ code: 'twake_drive' })[0] || {}).id, - Workspaces.currentWorkspaceId, - ); - if (!drive_channel && (this.props.initialDirectory || {}).id == directory_id) { - allow_go_parent = false; - } - - return ( -
-
- {directory.parent_id && allow_go_parent && ( - { - this.changeCurrentDirectory({ id: directory.parent_id }); - }} - /> - )}{' '} - {directory.parent_id - ? directory.name - : Languages.t('app.identity?.name.twake_drive', [], 'Documents')} -
-
- {directories.map((item, index) => ( -
DriveService.changeCurrentDirectory(this.drive_channel, item)} - > - -
- ))} - {files.map((item, index) => ( -
this.clickOnFile(item)} - > - -
- ))} -
- - {this.state.creating_folder && ( -
- - (node ? node.focus() : '')} - type="text" - defaultValue={''} - placeholder={Languages.t( - 'scenes.apps.drive.navigators.navigator_content.directory_name', - [], - 'Nom du dossier', - )} - onKeyPress={e => { - if (e.key === 'Enter') { - DriveService.createDirectory( - directory.workspace_id, - e.target.value, - directory, - DriveService.current_collection_key_channels[this.drive_channel], - res => { - this.changeCurrentDirectory(res); - }, - ); - this.setState({ creating_folder: false }); - } - }} - /> -
- )} - {!this.state.creating_folder && ( -
- {!this.state.creating_folder && directory.workspace_id && ( - - )} - {this.props.mode == 'select_location' && ( -
- )} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Drive/UI/Directory.js b/twake/frontend/src/app/components/Drive/UI/Directory.js deleted file mode 100755 index db430af88e..0000000000 --- a/twake/frontend/src/app/components/Drive/UI/Directory.js +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; - -import Icon from 'components/Icon/Icon.js'; -import FolderIcon from '@material-ui/icons/FolderOutlined'; -import Menu from 'components/Menus/Menu.js'; -import Numbers from 'services/utils/Numbers'; -import '../Drive.scss'; -import 'moment-timezone'; -import { getCompanyApplication as getApplication } from 'app/state/recoil/atoms/CompanyApplications'; - -export default class Directory extends React.Component { - constructor(props) { - super(); - } - render() { - var app = {}; - if (this.props.data.application_id && this.props.data.external_storage) { - app = getApplication(this.props.data.application_id); - } - - return [ -
-
- {!app.id && } - {!!app.id && ( -
- )} -
-
- {this.props.data.name} - {!!app.id && ({app.identity?.name})} -
- - {(this.props.data.acces_info || {}).token && ( - - )} - - {this.props.details && ( -
- {this.props.data.size ? Numbers.humanFileSize(this.props.data.size, true) : '-'} -
- )} - {this.props.menu && this.props.menu.length > 0 && ( - - - - )} -
, - ]; - } -} diff --git a/twake/frontend/src/app/components/Drive/UI/File.js b/twake/frontend/src/app/components/Drive/UI/File.js deleted file mode 100755 index f6de1e1e7c..0000000000 --- a/twake/frontend/src/app/components/Drive/UI/File.js +++ /dev/null @@ -1,120 +0,0 @@ -import React from 'react'; -import moment from 'moment'; -import 'moment-timezone'; - -import Icon from 'components/Icon/Icon'; -import Menu from 'components/Menus/Menu'; -import DriveService from 'services/Apps/Drive/Drive'; -import Numbers from 'services/utils/Numbers'; -import FileType from './FileType'; -import TagPicker from 'components/TagPicker/TagPicker'; -import { addApiUrlIfNeeded } from 'app/services/utils/URLUtils'; -import '../Drive.scss'; - -export default class File extends React.Component { - constructor(props) { - super(); - } - render() { - var mini = this.props.mini; - - var date = false; - if (this.props.data.modified) { - date = moment(this.props.data.modified * 1000); - } - if (this.props.data.added && this.props.isVersion) { - date = moment(this.props.data.added * 1000); - } - - var date_string = date ? date.format('L') : '-'; - if (new Date().getTime() - date.unix() * 1000 < 1000 * 23 * 60 * 60) { - date_string = date ? date.format('LT') : '-'; - } - - return [ -
-
- -
-
, -
-
- -
-
- {!!this.props.versionLabel &&
{this.props.versionLabel}
} - {this.props.data.name} - {!this.props.isVersion && (this.props.data.versions || {}).length > 1 && ( - - ({(this.props.data.versions || {}).length} versions) - - )} -    - -
- - {(this.props.data.acces_info || {}).token && ( - - )} - {this.props.data.url && } - - {/* -
- {this.state.element.created_by || "-"} -
- */} - {this.props.details && [ -
{date_string}
, -
- {this.props.data.size ? Numbers.humanFileSize(this.props.data.size, true) : '-'} -
, - ]} - {!this.props.isVersion && ( -
-
-
- )} - {this.props.menu && this.props.menu.length > 0 && ( - - - - )} - - {this.props.removeIcon === true && ( - - )} -
, - ]; - } -} diff --git a/twake/frontend/src/app/components/Drive/UI/FileType.js b/twake/frontend/src/app/components/Drive/UI/FileType.js deleted file mode 100755 index e0cc3f40aa..0000000000 --- a/twake/frontend/src/app/components/Drive/UI/FileType.js +++ /dev/null @@ -1,62 +0,0 @@ -import React, { Component } from 'react'; - -import Archive from '../Icons/archive.js'; -import Code from '../Icons/code.js'; -import Document from '../Icons/document.js'; -import Files from '../Icons/file.js'; -import Images from '../Icons/image.js'; -import Link from '../Icons/link.js'; -import Pdf from '../Icons/pdf.js'; -import Slide from '../Icons/slides.js'; -import Sound from '../Icons/sound.js'; -import Spreadsheet from '../Icons/spreadsheet.js'; -import Svg from '../Icons/svg.js'; -import Video from '../Icons/video.js'; - -export default class FileType extends React.Component { - /* props : type (string) */ - constructor(props) { - super(); - } - render() { - var type = this.props.type; - var TypeIcon = Files; - switch (type) { - case 'link': - TypeIcon = Link; - break; - case 'code': - TypeIcon = Code; - break; - case 'document': - TypeIcon = Document; - break; - case 'image': - TypeIcon = Images; - break; - case 'pdf': - TypeIcon = Pdf; - break; - case 'slides': - TypeIcon = Slide; - break; - case 'sound': - TypeIcon = Sound; - break; - case 'spreadsheet': - TypeIcon = Spreadsheet; - break; - case 'svg': - TypeIcon = Svg; - break; - case 'video': - TypeIcon = Video; - break; - case 'archive': - TypeIcon = Archive; - break; - default: - } - return ; - } -} diff --git a/twake/frontend/src/app/components/Drive/VersionDetails.js b/twake/frontend/src/app/components/Drive/VersionDetails.js deleted file mode 100755 index a53a26ffec..0000000000 --- a/twake/frontend/src/app/components/Drive/VersionDetails.js +++ /dev/null @@ -1,128 +0,0 @@ -import React from 'react'; -import Languages from 'services/languages/languages'; -import Icon from 'components/Icon/Icon.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import DriveService from 'services/Apps/Drive/Drive.js'; -import UploadZone from 'components/Uploads/UploadZone'; -import WorkspaceUserRights from 'services/workspaces/WorkspaceUserRights'; -import MediumPopupManager from 'app/components/Modal/ModalManager'; -import { ObjectModal, ObjectModalTitle } from 'components/ObjectModal/DeprecatedObjectModal.js'; -import UIFile from './UI/File.js'; -import 'moment-timezone'; - -import './Drive.scss'; - -export default class VersionDetails extends React.Component { - constructor() { - super(); - this.state = { - workspaces: Workspaces, - i18n: Languages, - }; - Languages.addListener(this); - DriveService.addListener(this); - Collections.get('drive').addListener(this); - } - componentWillUnmount() { - Languages.removeListener(this); - DriveService.removeListener(this); - Collections.get('drive').removeListener(this); - } - render() { - var countVersion = (this.props.file.versions || []).length; - return ( - MediumPopupManager.closeAll()} - footer={ -
-
-
{ - if (this.upload_zone) { - this.upload_zone.open(); - } - }} - > -
- -
-
- {Languages.t('components.drive.new_versions', [], 'Ajouter une nouvelle version')} -
-
-
-
- } - title={ -
- - {Languages.t('scenes.apps.drive.right_preview.versions', [], 'Versions')} - -
- } - > -
- (this.upload_zone = node)} - driveCollectionKey={''} - parent={this.props.file.parent_id} - driveCollectionKey={{ id: this.props.file.parent_id }} - uploadOptions={{ - workspace_id: this.state.workspaces.currentWorkspaceId, - new_version: true, - file_id: this.props.file.id, - }} - allowPaste={true} - > - {(this.props.file.versions || []) - .sort((a, b) => { - return b.added - a.added; - }) - .map((version, index) => { - var data = {}; - if (index > 0) { - data.extension = this.props.file.extension; - data.name = version.name; - data.creator = version.creator; - data.size = version.size; - } else { - data = JSON.parse(JSON.stringify(this.props.file)); - } - data.added = version.added; - return ( -
- { - var link = DriveService.getLink(this.props.file, version.id, 1); - window.open(link); - }, - }, - ]} - details={true} - /> -
- ); - })} -
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/EditableText/EditableText.js b/twake/frontend/src/app/components/EditableText/EditableText.js deleted file mode 100755 index 1e3e152406..0000000000 --- a/twake/frontend/src/app/components/EditableText/EditableText.js +++ /dev/null @@ -1,26 +0,0 @@ -import React, { Component } from 'react'; -import './EditableText.scss'; - -import Input from 'components/Inputs/Input.js'; - -export default class EditableText extends React.Component { - constructor(props) { - super(); - this.props = props; - - this.state = { - value: '#FF0000', - }; - } - render() { - return ( -
- this.setState({ value: evt.target.value })} - /> -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/EmojiPicker/EmojiPicker.js b/twake/frontend/src/app/components/EmojiPicker/EmojiPicker.js deleted file mode 100755 index e3ddba0840..0000000000 --- a/twake/frontend/src/app/components/EmojiPicker/EmojiPicker.js +++ /dev/null @@ -1,144 +0,0 @@ -import React from 'react'; -import { Picker } from 'emoji-mart'; -import Emojione from 'components/Emojione/Emojione'; -import { getAsFrontUrl } from 'app/services/utils/URLUtils'; -import './EmojiPicker.scss'; -import 'emoji-mart/css/emoji-mart.css'; -import Languages from 'services/languages/languages'; -import { isArray } from 'lodash'; - -Picker.defaultProps.backgroundImageFn = function backgroundImageFn(set, sheetSize) { - sheetSize = 20; - return getAsFrontUrl( - '/public/emoji-datasource/'.concat(set, '/sheets-256/').concat(sheetSize, '.png'), - ); -}; -export default class EmojiPicker extends React.Component { - /* - props = { - preferedEmoji : Array of emoji's shortname - onChange : called when a smiley is selected - } - */ - constructor(props) { - super(); - this.props = props; - this.state = { - suggestions: [], - currentTitle: '', - availableCategories: [], - scrollToRow: 0, - loaded: false, - }; - this.currentTitleIndex = 100000; - this.clickScrollToRow = 0; - } - componentWillUnmount() {} - onUpdate(item) {} - onRemove(item, ev) {} - onChange(list) { - if (list.length > 0) { - if (this.props.onChange) { - this.props.onChange(list[0]); - } - this.setState({ list: [] }); - } - } - renderItemChoosen(item) { - return ( -
- -
- ); - } - renderItem(item) { - return ( -
- -
- ); - } - scrollToCategory(category) { - var index = 0; - this.state.suggestions.forEach((item, i) => { - if (item.value == category) { - index = i; - return false; - } - }); - this.clickScrollToRow = index; - if (this.state.scrollToRow != index) { - this.setState({ scrollToRow: index }); - } else { - this.list_node.forceUpdateGrid(); - } - } - select(emoji) { - if (this.picker) { - this.picker.onSelect(emoji); - } else { - this.onChange([emoji]); - } - } - getPrefered() { - var pref = this.props.preferedEmoji || [ - ':thumbsup:', - ':thumbsdown:', - ':hearts:', - ':tada:', - ':smile:', - ':confused:', - ]; - if ( - typeof this.props.selected === 'string' && - this.props.selected && - pref.indexOf(this.props.selected) < 0 - ) { - pref.unshift(this.props.selected); - } - if (isArray(this.props.selected)) { - this.props.selected.forEach(s => pref.unshift(s)); - } - return pref; - } - componentDidMount() { - setTimeout(() => { - this.setState({ loaded: true }); - }, 300); - } - render() { - if (!this.state.loaded) { - return
; - } - return ( -
- -
- ); - } -} diff --git a/twake/frontend/src/app/components/Emojione/Emojione.tsx b/twake/frontend/src/app/components/Emojione/Emojione.tsx deleted file mode 100755 index 1c817683f6..0000000000 --- a/twake/frontend/src/app/components/Emojione/Emojione.tsx +++ /dev/null @@ -1,108 +0,0 @@ -//@ts-nocheck -//We need this because of a bug in emoji_mart fallback implementationimport React, { Component } from 'react'; - -import React, { Component } from 'react'; - -import 'emoji-mart/css/emoji-mart.css'; - -import { getEmojiDataFromNative, Emoji } from 'emoji-mart'; -import data from 'emoji-mart/data/all.json'; - -import emojione from 'emojione'; -import Icon from 'components/Icon/Icon.js'; - -import './Emojione.scss'; -import { getAsFrontUrl } from 'app/services/utils/URLUtils'; - -type Props = { - type: string; - size?: number; - className?: string; - s64?: boolean; - s128?: boolean; - emoji?: string; -}; - -const type_to_uni: any = {}; - -const getFromEmojione = (props: Props) => { - //Use from local server - let html: string | '' = ''; - html = emojione.toImage(props.type || props.emoji || ''); - html = html?.replace('https://cdn.jsdelivr.net/emojione/assets/3.1/png/', '/public/emojione/'); - - if (props.s64) { - html = html?.replace('/32/', '/64/'); - } else if (props.s128) { - html = html?.replace('/32/', '/128/'); - } - return { __html: html }; -}; - -class EmojioneFallback extends Component { - // WIP - render() { - return ( - - ); - } -} - -export default React.memo((props: Props) => { - if (typeof props.type != 'string') { - return <>; - } - - if (props.type === 'trash') { - return ; - } - - if (props.type.substr(0, 7) === ':twake-') { - return ( - - ); - } - - if (props.type.substr(0, 7) === 'http://' || props.type.substr(0, 8) === 'https://') { - return ( - - ); - } - - let size = props.size || 16; - if (size > 32 || props.s64 || props.s128) { - return ; - } - - const uni = - type_to_uni[props.type] || - //@ts-ignore - getEmojiDataFromNative(emojione.shortnameToUnicode(props.type), 'apple', data); - type_to_uni[props.type] = uni; - - return ( - - { - if ([16, 20, 32, 64].indexOf(size) < 0) { - size = 64; - } - return (getAsFrontUrl('/public/emoji-datasource/'.concat(set, '/sheets-256/').concat(size, '.png'))); - }} - emoji={uni || props.type} - set="apple" - size={size} - fallback={() => } - /> - - ); -}); diff --git a/twake/frontend/src/app/components/File/File.scss b/twake/frontend/src/app/components/File/File.scss deleted file mode 100644 index 3b8db65614..0000000000 --- a/twake/frontend/src/app/components/File/File.scss +++ /dev/null @@ -1,99 +0,0 @@ -.file-component { - border: 1px solid var(--grey-light); - box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.1); - border-radius: 8px 8px 8px 8px; - width: 218px; - display: flex; - flex-direction: column; - justify-content: space-between; - - &:hover { - cursor: pointer; - } - - &.file-component-uploading { - opacity: 0.5; - border-radius: 8px 8px 0px 0px; - - .file-info-container { - padding-bottom: 0; - } - - .file-progress-bar-container { - padding-top: 8px; - height: 2px; - } - } - - &.file-component-error { - background: var(--error-background); - } - - .file-info-container { - display: flex; - flex-direction: row; - justify-content: space-between; - padding: 8px 8px 6px 8px; - - .file-thumbnail-container { - display: flex; - align-items: center; - justify-content: center; - width: 32px; - - .file-thumbnail-component { - border-radius: 4px; - } - } - - .file-component-details { - overflow: hidden; - flex: 1; - display: flex; - flex-direction: column; - - .ant-tag { - height: 15px; - line-height: 15px; - padding: 0 4px; - } - } - } - - .file-menu { - display: flex; - - align-items: center; - justify-content: space-between; - - .ant-btn { - display: flex; - justify-content: center; - align-items: center; - &:hover { - color: var(--black); - } - color: var(--grey-dark); - background-color: transparent; - } - } -} - -.file-progress-bar-container { - display: flex; - - .file-progress-bar { - .ant-progress-outer { - height: 2px; - display: flex; - - .ant-progress-inner { - .ant-progress-bg { - border-radius: 0 0 8px 8px; - height: 2px !important; - transition: all 0.2s; - } - } - } - } -} diff --git a/twake/frontend/src/app/components/File/FileComponent.tsx b/twake/frontend/src/app/components/File/FileComponent.tsx deleted file mode 100644 index 75a64e125d..0000000000 --- a/twake/frontend/src/app/components/File/FileComponent.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import classNames, { Argument } from 'classnames'; - -import { FileThumbnail, FileDetails, FileActions, FileProgress } from './parts'; -import { - isPendingFileStatusCancel, - isPendingFileStatusError, - isPendingFileStatusSuccess, -} from 'app/components/FileUploads/utils/PendingFiles'; -import { DataFileType } from './types'; -import DriveService from 'services/Apps/Drive/Drive.js'; -import FileUploadService from '../FileUploads/FileUploadService'; -import RouterService from 'app/services/RouterService'; - -import './File.scss'; -import { PendingFileRecoilType } from 'app/models/File'; -import Api from 'app/services/Api'; - -type PropsType = { - source: 'internal' | 'drive' | string; - externalId: string | any; - file: DataFileType; - context: 'input' | 'message' | 'drive'; - progress?: number; - status?: PendingFileRecoilType['status']; - onRemove?: Function; - className?: string; -}; - -export default ({ - source, - externalId, - file, - className, - context, - progress, - status, - onRemove, -}: PropsType) => { - const { companyId } = RouterService.getStateFromRoute(); - const classNameArguments: Argument[] = [ - 'file-component', - className, - { - 'file-component-error': - status && (isPendingFileStatusError(status) || isPendingFileStatusCancel(status)), - 'file-component-uploading': progress && progress < 1, - }, - ]; - - const onClickFile = async (data: DataFileType, companyId: string) => { - if (source === 'internal') { - //Only if upload has ended - if (!status || isPendingFileStatusSuccess(status)) - DriveService.viewDocument( - { - id: file.id, - name: file.name, - url: FileUploadService.getDownloadRoute({ companyId, fileId: file.id }), - extension: file.name.split('.').pop(), - }, - true, - ); - } - if (source === 'drive') { - const file = (await Api.post('/ajax/drive/v2/find', { - options: { - element_id: externalId?.id, - workspace_id: externalId?.workspace_id, - }, - })) as any; - DriveService.viewDocument(file?.data, context === 'input'); - } - }; - return ( -
companyId && onClickFile(file, companyId)} - > -
- - - -
- -
- ); -}; diff --git a/twake/frontend/src/app/components/File/parts/thumbnail.tsx b/twake/frontend/src/app/components/File/parts/thumbnail.tsx deleted file mode 100644 index 6a77b5ad36..0000000000 --- a/twake/frontend/src/app/components/File/parts/thumbnail.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import classNames from 'classnames'; -import { FileText, Film, Headphones, Archive, Link } from 'react-feather'; -import { DataFileType } from '../types'; - -type PropsType = { - file: DataFileType; -}; - -export const FileThumbnail = ({ file }: PropsType): JSX.Element => { - const type = file.type; - - return ( -
- {type === 'image' ? ( -
- ) : ( - <> - )} - {type === 'video' ? : <>} - {type === 'sound' ? : <>} - {type === 'archive' ? : <>} - {type === 'link' ? : <>} - {type === 'other' ? : <>} -
- ); -}; - -export default FileThumbnail; diff --git a/twake/frontend/src/app/components/File/types.ts b/twake/frontend/src/app/components/File/types.ts deleted file mode 100644 index 5c34121329..0000000000 --- a/twake/frontend/src/app/components/File/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { PendingFileRecoilType } from 'app/models/File'; - -export type DataFileType = { - id: string; - name: string; - thumbnail?: string; - company_id?: string; - size: number; - type: string; -}; diff --git a/twake/frontend/src/app/components/FileUploads/FileUploadAPIClient.ts b/twake/frontend/src/app/components/FileUploads/FileUploadAPIClient.ts deleted file mode 100644 index 1c79fa9a53..0000000000 --- a/twake/frontend/src/app/components/FileUploads/FileUploadAPIClient.ts +++ /dev/null @@ -1,116 +0,0 @@ -import Api from 'app/services/Api'; -import { FileType } from 'app/models/File'; -import { MessageFileType } from 'app/models/Message'; -import extensionToMime from './utils/extensionToMime'; - -type ResponseFileType = { resource: FileType }; -type ResponseDeleteFileType = { status: 'success' | 'error' }; - -type BaseContentType = { companyId: string }; -type GetContextType = BaseContentType & { fileId: string }; -type DeleteContextType = BaseContentType & { fileId: string }; -type DownloadContextType = BaseContentType & { fileId: string }; - -type FileTypes = - | 'link' - | 'code' - | 'document' - | 'image' - | 'pdf' - | 'slides' - | 'sound' - | 'spreadsheet' - | 'video' - | 'archive' - | 'other'; - -class FileUploadAPIClient { - private readonly prefixUrl: string = '/internal/services/files/v1'; - - public upload(file: File, context: BaseContentType): Promise { - const uploadFileRoute = `${this.getRoute({ companyId: context.companyId })}?filename=${ - file.name - }&type=${file.type}&total_size=${file.size}`; - - return Api.post(uploadFileRoute, undefined); - } - - public get({ companyId, fileId }: GetContextType): Promise { - const getFileRoute = this.getRoute({ fileId, companyId }); - - return Api.get(getFileRoute); - } - - public getRoute({ - companyId, - fileId = undefined, - fullApiRouteUrl = false, - download, - }: { - companyId: string; - fileId?: string; - fullApiRouteUrl?: boolean; - download?: boolean; - }): string { - const route = `${this.prefixUrl}/companies/${companyId}/files${ - fileId !== undefined ? `/${fileId}${download ? '/download' : ''}` : '' - }`; - - return fullApiRouteUrl ? Api.route(route) : route; - } - - public getFileThumbnailUrl(file: Pick): string { - if (!file.thumbnails?.[0]?.index) return ''; - return `${this.getRoute({ - companyId: file.company_id, - fileId: file.id, - fullApiRouteUrl: true, - })}/thumbnails/${file.thumbnails?.[0]?.index}`; - } - - public getFileThumbnailUrlFromMessageFile(file: MessageFileType): string { - if (file.metadata?.source !== 'internal') return file.metadata?.thumbnails?.[0]?.url || ''; - return `${this.getRoute({ - companyId: - (typeof file.metadata?.external_id === 'string' - ? file.company_id - : file.metadata?.external_id?.company_id) || '', - fileId: - (typeof file.metadata?.external_id === 'string' - ? file.metadata?.external_id - : file.metadata?.external_id?.id) || '', - fullApiRouteUrl: true, - })}/thumbnails/${file.metadata?.thumbnails?.[0]?.index}`; - } - - public delete({ companyId, fileId }: DeleteContextType): Promise { - const deleteFileRoute = this.getRoute({ companyId, fileId }); - return Api.delete(deleteFileRoute, undefined); - } - - public download({ companyId, fileId }: DownloadContextType): Promise { - const downloadFileRoute = this.getRoute({ companyId, fileId, download: true }); - return Api.get(downloadFileRoute, undefined, true, { - withBlob: true, - }); - } - - public getDownloadRoute({ companyId, fileId }: DownloadContextType): string { - return this.getRoute({ companyId, fileId, download: true, fullApiRouteUrl: true }); - } - - public mimeToType(mime: string): FileTypes { - if (mime.split('/')[0] === 'image') return 'image'; - if (mime.split('/')[0] === 'video') return 'video'; - if (mime.split('/')[0] === 'audio') return 'sound'; - if (mime === 'application/zip' || mime === 'application/vnd.rar') return 'archive'; - //TODO add other types - return 'other'; - } - - public extensionToMime(extension: string): string { - return extensionToMime[extension] || ''; - } -} - -export default new FileUploadAPIClient(); diff --git a/twake/frontend/src/app/components/FileUploads/FileUploadService.ts b/twake/frontend/src/app/components/FileUploads/FileUploadService.ts deleted file mode 100644 index 73d1489ee1..0000000000 --- a/twake/frontend/src/app/components/FileUploads/FileUploadService.ts +++ /dev/null @@ -1,258 +0,0 @@ -import { v1 as uuid } from 'uuid'; -import EventEmitter from 'events'; - -import { FileType, PendingFileType } from 'app/models/File'; -import JWTStorage from 'app/services/JWTStorage'; -import RouterServices from 'services/RouterService'; -import Resumable from 'services/uploadManager/resumable'; -import FileUploadAPIClient from './FileUploadAPIClient'; -import { isPendingFileStatusPending } from './utils/PendingFiles'; -import Logger from 'app/services/Logger'; -import _ from 'lodash'; - -export enum Events { - ON_CHANGE = 'notify', -} - -const logger = Logger.getLogger('Services/FileUploadService'); -class FileUploadService { - private pendingFiles: PendingFileType[] = []; - public currentTaskId: string = ''; - private recoilHandler: Function = () => {}; - - setRecoilHandler(handler: Function) { - this.recoilHandler = handler; - } - - notify() { - const updatedState = this.pendingFiles.map((f: PendingFileType) => { - return { - id: f.id, - status: f.status, - progress: f.progress, - file: f.backendFile, - }; - }); - this.recoilHandler(_.cloneDeep(updatedState)); - } - - public async upload(fileList: File[]): Promise { - const { companyId } = RouterServices.getStateFromRoute(); - - if (!fileList || !companyId) { - logger.log('FileList or companyId is undefined', [fileList, companyId]); - return []; - } - - if (!this.pendingFiles.some(f => isPendingFileStatusPending(f.status))) { - //New upload task when all previous task is finished - this.currentTaskId = uuid(); - } - - fileList.forEach(async file => { - if (!file) return; - - const pendingFile: PendingFileType = { - id: uuid(), - status: 'pending', - progress: 0, - lastProgress: new Date().getTime(), - speed: 0, - uploadTaskId: this.currentTaskId, - originalFile: file, - backendFile: null, - resumable: null, - }; - - this.pendingFiles.push(pendingFile); - - this.notify(); - - // First we create the file object - const resource = (await FileUploadAPIClient.upload(file, { companyId }))?.resource; - - if (!resource) { - throw new Error('A server error occured'); - } - - pendingFile.backendFile = resource; - this.notify(); - - // Then we overwrite the file object with resumable - pendingFile.resumable = this.getResumableInstance({ - target: FileUploadAPIClient.getRoute({ - companyId, - fileId: pendingFile.backendFile.id, - fullApiRouteUrl: true, - }), - query: { - thumbnail_sync: 1, - }, - headers: { - Authorization: JWTStorage.getAutorizationHeader(), - }, - }); - - pendingFile.resumable.addFile(file); - - pendingFile.resumable.on('fileAdded', (f: any, message: any) => - pendingFile.resumable.upload(), - ); - - pendingFile.resumable.on('fileProgress', (f: any, ratio: number) => { - const bytesDelta = (f.progress() - pendingFile.progress) * pendingFile.originalFile.size; - const timeDelta = new Date().getTime() - pendingFile.lastProgress; - - // To avoid jumping time ? - if (timeDelta > 1000) { - pendingFile.speed = bytesDelta / timeDelta; - } - - pendingFile.backendFile = f; - pendingFile.lastProgress = new Date().getTime(); - pendingFile.progress = f.progress(); - this.notify(); - }); - - pendingFile.resumable.on('fileSuccess', (f: any, message: string) => { - try { - pendingFile.backendFile = JSON.parse(message).resource; - pendingFile.status = 'success'; - this.notify(); - } catch (e) { - logger.error(`Error on fileSuccess Event`, e); - } - }); - - pendingFile.resumable.on('fileError', (f: any, message: any) => { - pendingFile.status = 'error'; - pendingFile.resumable.cancel(); - this.notify(); - }); - }); - - return this.pendingFiles.filter(f => f.uploadTaskId === this.currentTaskId); - } - - public async getFile({ - companyId, - fileId, - }: { - fileId: string; - companyId: string; - }): Promise { - return _.cloneDeep((await FileUploadAPIClient.get({ fileId, companyId }))?.resource); - } - - public getPendingFile(id: string): PendingFileType { - return this.pendingFiles.filter(f => f.id === id)[0]; - } - - public getPendingFileByBackendId(id: string): PendingFileType { - return this.pendingFiles.filter(f => f.backendFile?.id && f.backendFile.id === id)[0]; - } - - public cancel(id: string, timeout = 1000) { - const fileToCancel = this.pendingFiles.filter(f => f.id === id)[0]; - - fileToCancel.status = 'cancel'; - fileToCancel.resumable.cancel(); - this.notify(); - - if (fileToCancel.backendFile) - this.deleteOneFile({ - companyId: fileToCancel.backendFile.company_id, - fileId: fileToCancel.backendFile.id, - }); - - setTimeout(() => { - this.pendingFiles = this.pendingFiles.filter(f => f.id !== id); - this.notify(); - }, timeout); - } - - public retry(id: string) { - const fileToRetry = this.pendingFiles.filter(f => f.id === id)[0]; - - if (fileToRetry.status === 'error') { - fileToRetry.status = 'pending'; - fileToRetry.resumable.upload(); - - this.notify(); - } - } - - public pauseOrResume(id: string) { - const fileToCancel = this.pendingFiles.filter(f => f.id === id)[0]; - - fileToCancel.status !== 'pause' - ? (fileToCancel.status = 'pause') - : (fileToCancel.status = 'pending'); - fileToCancel.status === 'pause' - ? fileToCancel.resumable.pause() - : fileToCancel.resumable.upload(); - - this.notify(); - } - - private getResumableInstance({ - target, - headers, - chunkSize, - testChunks, - simultaneousUploads, - maxChunkRetries, - query, - }: { - target: string; - headers: { Authorization: string }; - chunkSize?: number; - testChunks?: number; - simultaneousUploads?: number; - maxChunkRetries?: number; - query?: { [key: string]: any }; - }) { - return new Resumable({ - target, - headers, - chunkSize: chunkSize || 50000000, - testChunks: testChunks || false, - simultaneousUploads: simultaneousUploads || 5, - maxChunkRetries: maxChunkRetries || 2, - query, - }); - } - - public async deleteOneFile({ - companyId, - fileId, - }: { - companyId: string; - fileId: string; - }): Promise { - const response = await FileUploadAPIClient.delete({ companyId, fileId }); - - if (response.status === 'success') { - this.pendingFiles = this.pendingFiles.filter(f => f.backendFile?.id !== fileId); - this.notify(); - } else { - logger.error(`Error while processing delete for file`, fileId); - } - } - - public download({ companyId, fileId }: { companyId: string; fileId: string }): Promise { - return FileUploadAPIClient.download({ - companyId: companyId, - fileId: fileId, - }); - } - - public getDownloadRoute({ companyId, fileId }: { companyId: string; fileId: string }): string { - return FileUploadAPIClient.getDownloadRoute({ - companyId: companyId, - fileId: fileId, - }); - } -} - -export default new FileUploadService(); diff --git a/twake/frontend/src/app/components/FileUploads/PendingFileComponents/PendingFileRow.tsx b/twake/frontend/src/app/components/FileUploads/PendingFileComponents/PendingFileRow.tsx deleted file mode 100644 index 01900e7722..0000000000 --- a/twake/frontend/src/app/components/FileUploads/PendingFileComponents/PendingFileRow.tsx +++ /dev/null @@ -1,195 +0,0 @@ -import React from 'react'; -import { PauseCircle, PlayCircle, Trash2, X } from 'react-feather'; -import { Row, Col, Typography, Divider, Progress, Button, Tooltip } from 'antd'; -import { capitalize } from 'lodash'; - -import { - isPendingFileStatusCancel, - isPendingFileStatusError, - isPendingFileStatusPause, - isPendingFileStatusPending, - isPendingFileStatusSuccess, -} from '../utils/PendingFiles'; -import Languages from 'services/languages/languages'; -import { useUpload } from 'app/state/recoil/hooks/useUpload'; -import { PendingFileRecoilType, PendingFileType } from 'app/models/File'; - -import '../../File/File.scss'; - -type PropsType = { - pendingFileState: PendingFileRecoilType; - pendingFile: PendingFileType; -}; - -const { Text } = Typography; -export default ({ pendingFileState, pendingFile }: PropsType) => { - const { pauseOrResumeUpload, cancelUpload } = useUpload(); - - const getProgressStrokeColor = (status: PendingFileRecoilType['status']) => { - if (isPendingFileStatusCancel(status)) return 'var(--error)'; - if (isPendingFileStatusError(status)) return 'var(--error)'; - if (isPendingFileStatusPause(status)) return 'var(--warning)'; - if (isPendingFileStatusPending(status)) return 'var(--progress-bar-color)'; - - return 'var(--success)'; - }; - - const setStatus = () => { - switch (pendingFileState.status) { - case 'error': - case 'pause': - case 'cancel': - return 'exception'; - case 'pending': - return 'active'; - case 'success': - return 'success'; - default: - return 'normal'; - } - }; - - return ( -
- - - {pendingFile.originalFile.name ? ( - - - {capitalize(pendingFile.originalFile.name)} - - {isPendingFileStatusPause(pendingFile.status) && ( - - {/* TODO Add translation here */} - (paused) - - )} - - ) : ( -
- )} - - - - {pendingFileState.id ? ( - !isPendingFileStatusSuccess(pendingFileState.status) && - !isPendingFileStatusError(pendingFileState.status) ? ( - - -
- )} -
-
(this.dom_fake_separator_top = node)} /> -
(this.dom_visualized_messages_top = node)} - > - {this.state.messages.map((message, _i) => { - if (this.compare(message, this.messages_med) <= 0) { - var tmp = previous_message; - previous_message = message; - var i = _i; - return ( -
- (this.dom_messages[i] = { - node: node, - message: message, - scrollTop: (this.dom_messages[i] || {}).scrollTop, - }) - } - > - {this.props.renderMessage(message, tmp, () => this.measure(message))} -
- ); - } - })} -
-
(this.dom_visualized_messages_bottom = node)} - > - {this.state.messages.map((message, _i) => { - if (this.compare(message, this.messages_med) > 0) { - var tmp = previous_message; - previous_message = message; - var i = _i; - return ( -
- (this.dom_messages[i] = { - node: node, - message: message, - scrollTop: (this.dom_messages[i] || {}).scrollTop, - }) - } - > - {this.props.renderMessage(message, tmp, () => this.measure(message))} -
- ); - } - })} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/InfiniteMessages/InfiniteMessagesTester.js b/twake/frontend/src/app/components/InfiniteMessages/InfiniteMessagesTester.js deleted file mode 100755 index d3098e3fb1..0000000000 --- a/twake/frontend/src/app/components/InfiniteMessages/InfiniteMessagesTester.js +++ /dev/null @@ -1,74 +0,0 @@ -import React, { Component } from 'react'; - -import InfiniteMessages from './InfiniteMessages.js'; - -export default class InfiniteMessagesTester extends Component { - constructor() { - super(); - - ///////// Simulate messages - this.messages = []; - this.i = 0; - for (this.i; this.i < 10000; this.i++) { - this.messages.push({ - content: 'message ' + this.i, - height: 40 + Math.random() * 100, - id: this.i, - }); - } - setInterval(() => { - this.messages.push({ - content: 'message ' + this.i, - height: 40 + Math.random() * 100, - id: this.i, - }); - this.i++; - this.setState({}); - }, 1000); - /////////// - - this.infinieMessages = null; - } - getMessages(offset, limit, callback) { - if (!offset) { - setTimeout(() => { - callback(this.messages.slice(this.messages.length - limit, this.messages.length)); - }, 10); - } else { - var offsetPos = 0; - this.messages.every(m => { - if (m.id >= offset) { - return false; - } - offsetPos++; - return true; - }); - - setTimeout(() => { - if (limit > 0) { - callback(this.messages.slice(offsetPos - limit, offsetPos)); - } else { - callback(this.messages.slice(offsetPos + 1, offsetPos - limit)); - } - }, 10); - } - } - render() { - return ( -
- (this.infinieMessages = node)} - getMessages={(offset, limit, callback) => this.getMessages(offset, limit, callback)} - messages={this.messages} - offsetKey={'id'} - top={''} - renderMessage={(message, oldmessage, measure) => ( -
- {message.content} -
- )} - /> -
- ); - } -} diff --git a/twake/frontend/src/app/components/InlineTagPicker/InlineTagPicker.js b/twake/frontend/src/app/components/InlineTagPicker/InlineTagPicker.js deleted file mode 100644 index 4f8c74fb48..0000000000 --- a/twake/frontend/src/app/components/InlineTagPicker/InlineTagPicker.js +++ /dev/null @@ -1,27 +0,0 @@ -import React, { Component } from 'react'; -import './InlineTagPicker.scss'; - -export default class InlineTagPicker extends Component { - render() { - return this.props.available.map(item => { - return ( -
{ - let array = (this.props.value || []).map(a => a); - if (this.props.value.includes(item)) { - array = this.props.value.filter(val => item !== val); - } else { - array.push(item); - } - this.props.onChange(array); - }} - > - {item} -
- ); - }); - } -} diff --git a/twake/frontend/src/app/components/InputWithClipBoard/InputWithClipBoard.js b/twake/frontend/src/app/components/InputWithClipBoard/InputWithClipBoard.js deleted file mode 100755 index 12917ca8ed..0000000000 --- a/twake/frontend/src/app/components/InputWithClipBoard/InputWithClipBoard.js +++ /dev/null @@ -1,60 +0,0 @@ -import React, { Component } from 'react'; - -import Languages from 'services/languages/languages'; -import Icon from 'components/Icon/Icon.js'; -import Tooltip from 'components/Tooltip/Tooltip.js'; -import Input from 'components/Inputs/Input.js'; -import InputWithButton from 'components/Inputs/InputWithButton.js'; - -export default class InputWithClipBoard extends Component { - /* - props = { - value : "", - disabled : true|false - } - */ - constructor(props) { - super(props); - this.props = props; - - this.state = { - i18n: Languages, - }; - - Languages.addListener(this); - this.inputElement = false; - } - componentWillUnmount() { - Languages.removeListener(this); - } - selectAll() { - this.inputElement.focus(); - this.inputElement.select(); - } - copy() { - this.inputElement.disabled = false; - this.inputElement.focus(); - this.inputElement.select(); - document.execCommand('copy'); - this.inputElement.disabled = this.props.disabled; - this.tooltip.openWithTimeOut(2); - } - render() { - return ( - (this.tooltip = obj)} - overable={false} - tooltip={Languages.t('components.input.copied', [], 'Copié')} - > - (this.inputElement = obj)} - btnAction={() => this.copy()} - icon="copy" - hideBtn={this.props.hideBtn} - value={this.props.value} - disabled={this.props.disabled} - /> - - ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/Checkbox.js b/twake/frontend/src/app/components/Inputs/Checkbox.js deleted file mode 100755 index 30cd15eb79..0000000000 --- a/twake/frontend/src/app/components/Inputs/Checkbox.js +++ /dev/null @@ -1,92 +0,0 @@ -import React, { Component } from 'react'; - -import './Inputs.scss'; -import CheckIcon from '@material-ui/icons/CheckOutlined'; - -export default class Checkbox extends React.Component { - constructor(props) { - super(); - } - renderSwitch() { - var className = this.props.className || ''; - - if (this.props.big) { - className += ' big '; - } - if (this.props.medium) { - className += ' medium '; - } - if (this.props.small) { - className += ' small '; - } - - if ( - className.indexOf('medium') === className.indexOf('small') && - className.indexOf('big') === className.indexOf('small') && - className.indexOf('big') < 0 - ) { - className += ' medium'; - } - - return ( -
{ - if (!this.props.label && !this.props.disabled) { - this.props.onChange(!this.props.value); - } - }} - > -
- -
-
- ); - } - render() { - var parentClassName = ''; - - if (this.props.big) { - parentClassName += ' big '; - } - if (this.props.medium) { - parentClassName += ' medium '; - } - if (this.props.small) { - parentClassName += ' small '; - } - - if ( - parentClassName.indexOf('medium') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') < 0 - ) { - parentClassName += ' medium'; - } - - if (this.props.label) { - return ( -
{ - if (!this.props.disabled) { - this.props.onChange(!this.props.value); - } - }} - > - {this.renderSwitch()} -
{this.props.label}
-
- ); - } else { - return this.renderSwitch(); - } - } -} diff --git a/twake/frontend/src/app/components/Inputs/Input.js b/twake/frontend/src/app/components/Inputs/Input.js deleted file mode 100755 index 976f10aa45..0000000000 --- a/twake/frontend/src/app/components/Inputs/Input.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, { Component } from 'react'; - -import AutoHeight from 'components/AutoHeight/AutoHeight.js'; - -import './Inputs.scss'; - -export default class Input extends React.Component { - constructor(props) { - super(); - } - onKeyDown(evt) { - if (evt.keyCode == 13 && this.props.onEnter) { - this.props.onEnter(); - } - if (evt.keyCode == 27 && this.props.onEchap) { - this.props.onEchap(); - } - } - componentDidMount() { - if (this.props.autoFocus && this.node) { - this.node.focus(); - this.node.setSelectionRange(0, Number.MAX_SAFE_INTEGER); - } - } - render() { - var className = this.props.className || ''; - - if (this.props.big) { - className += ' big '; - } - if (this.props.medium) { - className += ' medium '; - } - if (this.props.small) { - className += ' small '; - } - - if ( - className.indexOf('medium') === className.indexOf('small') && - className.indexOf('big') === className.indexOf('small') && - className.indexOf('big') < 0 - ) { - className += ' medium'; - } - - if (this.props.autoHeight) { - return ( - { - this.node = node; - this.props.refInput && this.props.refInput(node); - }} - {...this.props} - onKeyDown={evt => { - if (this.props.onKeyDown) { - this.props.onKeyDown(evt); - } - this.onKeyDown(evt); - }} - className={'input ' + (className || '')} - /> - ); - } - - return ( - { - this.node = node; - this.props.refInput && this.props.refInput(node); - }} - {...this.props} - onKeyDown={evt => { - if (this.props.onKeyDown) { - this.props.onKeyDown(evt); - } - this.onKeyDown(evt); - }} - className={'input ' + (className || '')} - onBlur={this.props.onBlur} - onChange={this.props.onChange} - /> - ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputEnter.js b/twake/frontend/src/app/components/Inputs/InputEnter.js deleted file mode 100755 index 7c86362d31..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputEnter.js +++ /dev/null @@ -1,46 +0,0 @@ -import React, { Component } from 'react'; - -import Input from './Input.js'; -import Icon from 'components/Icon/Icon.js'; -import './Inputs.scss'; - -export default class InputEnter extends React.Component { - constructor(props) { - super(); - } - render() { - var className = this.props.className || ''; - var parentClassName = ''; - - if (this.props.big) { - parentClassName += ' big '; - } - if (this.props.medium) { - parentClassName += ' medium '; - } - if (this.props.small) { - parentClassName += ' small '; - } - - if ( - parentClassName.indexOf('medium') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') < 0 - ) { - parentClassName += ' medium'; - } - - return ( -
- - -
- ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputIcon.js b/twake/frontend/src/app/components/Inputs/InputIcon.js deleted file mode 100755 index 56bfefbe34..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputIcon.js +++ /dev/null @@ -1,47 +0,0 @@ -import React, { Component } from 'react'; - -import Input from './Input.js'; -import Icon from 'components/Icon/Icon.js'; -import './Inputs.scss'; - -export default class InputIcon extends React.Component { - constructor(props) { - super(); - } - render() { - var className = this.props.className || ''; - var parentClassName = ''; - - if (this.props.big) { - parentClassName += ' big '; - } - if (this.props.medium) { - parentClassName += ' medium '; - } - if (this.props.small) { - parentClassName += ' small '; - } - - if ( - parentClassName.indexOf('medium') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') === parentClassName.indexOf('small') && - parentClassName.indexOf('big') < 0 - ) { - parentClassName += ' medium'; - } - - return ( -
- - -
- ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputWithButton.js b/twake/frontend/src/app/components/Inputs/InputWithButton.js deleted file mode 100644 index f0403aa209..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputWithButton.js +++ /dev/null @@ -1,53 +0,0 @@ -import React, { Component } from 'react'; - -import Languages from 'services/languages/languages'; -import './InputWithButton.scss'; -import Icon from 'components/Icon/Icon.js'; -import Input from './Input.js'; - -export default class InputWithButton extends Component { - /* - props = { - value : "", - disabled : true|false - } - */ - constructor(props) { - super(props); - this.props = props; - - this.state = { - i18n: Languages, - }; - - Languages.addListener(this); - this.inputElement = false; - } - - componentWillUnmount() { - Languages.removeListener(this); - } - - render() { - return ( -
- { - this.inputElement = obj; - this.props.refInput && this.props.refInput(); - }} - {...this.props} - /> - {!this.props.hideBtn && ( -
this.props.btnAction()} - > - -
- )} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputWithColor.js b/twake/frontend/src/app/components/Inputs/InputWithColor.js deleted file mode 100755 index fd6b1cb70a..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputWithColor.js +++ /dev/null @@ -1,129 +0,0 @@ -import React, { Component } from 'react'; - -import MenusManager from 'app/components/Menus/MenusManager.js'; -import ColorPicker from 'components/ColorPicker/ColorPicker.js'; -import Input from 'components/Inputs/Input.js'; -import './Inputs.scss'; - -export default class InputWithColor extends React.Component { - constructor(props) { - super(); - } - componentWillMount() {} - outsideMenuListener() { - this.closeColorPicker(); - } - componentWillUnmount() { - document.removeEventListener('click', this.outsideClickListener); - } - componentDidMount() { - if (this.props.focusOnDidMount && this.input) { - this.input.focus(); - } - this.outsideClickListener = event => { - if ( - this.colorPickerIsOpen && - this.colorpicker_dom && - !this.colorpicker_dom.contains(event.target) && - document.contains(event.target) - ) { - this.outsideMenuListener(); - } - }; - this.outsideClickListener = this.outsideClickListener.bind(this); - document.addEventListener('click', this.outsideClickListener); - } - closeColorPicker() { - if (!this.colorPickerIsOpen) { - return; - } - - if (this.props.menu_level !== undefined) { - MenusManager.closeSubMenu(this.props.menu_level); - } else { - MenusManager.closeMenu(); - } - - this.colorPickerIsOpen = false; - } - openColorPicker() { - if (this.colorPickerIsOpen) { - return; - } - - var menu = [ - { - type: 'react-element', - reactElement: () => { - return ( - (this.colorpicker_dom = node)} - value={this.props.value[0]} - onChange={color => this.selectColor(color)} - /> - ); - }, - }, - ]; - var elementRect = window.getBoundingClientRect(this.color_dom); - elementRect.x = elementRect.x || elementRect.left; - elementRect.y = elementRect.y || elementRect.top; - if (this.props.menu_level !== undefined) { - MenusManager.openSubMenu(menu, elementRect, this.props.menu_level, 'bottom'); - } else { - MenusManager.openMenu(menu, elementRect, 'bottom'); - } - - setTimeout(() => { - this.colorPickerIsOpen = true; - }, 200); - } - selectColor(color) { - this.closeColorPicker(); - var value = [color, this.props.value[1]]; - this.onChange(value); - } - onChange(value) { - if (this.props.onChange) { - this.props.onChange(value); - } - } - render() { - if (!this.props.value[0]) { - this.onChange([ - ColorPicker.colors[parseInt(Math.random() * ColorPicker.colors.length)], - this.props.value[1], - ]); - } - return ( -
-
(this.color_dom = node)} - onClick={evt => { - this.openColorPicker(); - }} - > -
-
-
- (this.input = obj)} - type="text" - placeholder={this.props.placeholder} - value={this.props.value[1]} - onKeyDown={e => { - if (e.keyCode == 13 && this.props.onEnter) { - this.props.onEnter(); - } - }} - onChange={evt => { - if (this.onChange) this.onChange([this.props.value[0], evt.target.value]); - }} - /> -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputWithIcon.tsx b/twake/frontend/src/app/components/Inputs/InputWithIcon.tsx deleted file mode 100755 index e6084ae2b0..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputWithIcon.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import React from 'react'; -import { Input, Col, Row } from 'antd'; - -import Emojione from 'components/Emojione/Emojione'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import EmojiPicker from 'components/EmojiPicker/EmojiPicker.js'; - -import './Inputs.scss'; - -type PropsType = { [key: string]: any }; -type StateType = { [key: string]: any }; - -export default class InputWithIcon extends React.Component { - outsideClickListener: (event: any) => void = () => {}; - input: any; - emojiPickerIsOpen: any; - emojipicker_dom: any; - allChanEmojies = [ - ':8ball:', - ':dart:', - ':joystick:', - ':video_game:', - ':bar_chart:', - ':crystal_ball:', - ':speech_balloon:', - ':bulb:', - ':deciduous_tree:', - ':palm_tree:', - ':earth_americas:', - ':open_file_folder:', - ':penguin:', - ':seedling:', - ':sailboat:', - ':fire_engine:', - ':scroll:', - ':newspaper:', - ':factory:', - ':package:', - ':mailbox:', - ':moneybag:', - ':smiley_cat:', - ':sunglasses:', - ]; - emoji_dom: any; - - componentWillMount() { - this.randomizeEmojies(); - } - - randomizeEmojies() { - this.allChanEmojies.sort((a, b) => { - if (b === this.props.value[0]) { - return -1; - } - if (a === this.props.value[0]) { - return 1; - } - return Math.floor(Math.random() * 3) - 1; - }); - } - - outsideMenuListener() { - this.closeEmojiPicker(); - } - - componentWillUnmount() { - document.removeEventListener('click', this.outsideClickListener); - } - - componentDidMount() { - if (this.props.focusOnDidMount && this.input) { - this.input.focus(); - } - - this.outsideClickListener = event => { - if ( - this.emojiPickerIsOpen && - this.emojipicker_dom && - !this.emojipicker_dom.contains(event.target) && - document.contains(event.target) - ) { - this.outsideMenuListener(); - } - }; - - this.outsideClickListener = this.outsideClickListener.bind(this); - document.addEventListener('click', this.outsideClickListener); - } - - closeEmojiPicker() { - if (!this.emojiPickerIsOpen) { - return; - } - - if (this.props.menu_level !== undefined) { - MenusManager.closeSubMenu(this.props.menu_level); - } else { - MenusManager.closeMenu(); - } - - this.emojiPickerIsOpen = false; - } - - openEmojiPicker() { - if (this.emojiPickerIsOpen) { - return; - } - - var preferedEmojis = [this.props.value[0]]; - if (this.props.preferedEmoji) { - preferedEmojis = this.props.preferedEmoji; - } else { - this.randomizeEmojies(); - for (var i = 0; i < 5; i++) { - preferedEmojis[i + 1] = this.allChanEmojies[i]; - } - } - - var menu = [ - { - type: 'react-element', - className: 'menu-cancel-margin', - reactElement: () => { - return ( - (this.emojipicker_dom = node)} - onChange={(emoji: any) => this.selectEmoji(emoji)} - /> - ); - }, - }, - ]; - var elementRect = (window as any).getBoundingClientRect(this.emoji_dom); - elementRect.x = elementRect.x || elementRect.left; - elementRect.y = elementRect.y || elementRect.top; - if (this.props.menu_level !== undefined) { - MenusManager.openSubMenu(menu, elementRect, this.props.menu_level, 'bottom'); - } else { - MenusManager.openMenu(menu, elementRect, 'bottom', {}); - } - - setTimeout(() => { - this.emojiPickerIsOpen = true; - }, 200); - } - selectEmoji(emoji: any) { - this.closeEmojiPicker(); - var value = [emoji.native, this.props.value[1]]; - this.onChange(value); - } - onChange(value: any) { - if (this.props.onChange) { - this.props.onChange(value); - } - } - render() { - var icon = this.props.value[0]; - if (!this.props.value[0]) { - this.onChange([this.allChanEmojies[0], this.props.value[1]]); - icon = this.allChanEmojies[0]; - } - return ( - - - -
(this.emoji_dom = node)} - onClick={evt => { - this.openEmojiPicker(); - }} - > - -
- - - {(!this.props.children && ( - { - this.input = obj; - - this.props.inputRef(obj); - }} - type="text" - placeholder={this.props.placeholder} - value={this.props.value[1]} - onPressEnter={this.props.onEnter} - onChange={evt => { - if (this.onChange) this.onChange([this.props.value[0], evt.target.value]); - }} - /> - )) || - this.props.children} - -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Inputs/InputWithSelect.tsx b/twake/frontend/src/app/components/Inputs/InputWithSelect.tsx deleted file mode 100644 index c7864d0f9e..0000000000 --- a/twake/frontend/src/app/components/Inputs/InputWithSelect.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Input, Col, Row, Select, Typography, Button, Divider, Tooltip } from 'antd'; -import { ChannelType } from 'app/models/Channel'; -import { List, X } from 'react-feather'; -import Languages from 'services/languages/languages'; -import './InputWithSelect.scss'; - -type PropsType = { - channel: ChannelType | undefined; - onChange: (array: string[]) => void; - groups: string[]; -}; - -const { Group } = Input; -const { Option } = Select; -const InputWithSelect = ({ groups, channel, onChange }: PropsType): JSX.Element => { - const [group, setGroup] = useState(channel?.channel_group || ''); - const [channelName, setChannelName] = useState(channel?.name || ''); - const [searchedGroup, setSearchedGroup] = useState(''); - const [displaySelector, setDisplaySelector] = useState( - channel?.channel_group ? true : false, - ); - - useEffect(() => { - onChange([group || '', channelName]); - }); - - return ( - - - {!displaySelector && ( - - - - - {Languages.t('components.locked_features.locked_guests_popup.or')} - - -
- } - hideFooterDivider - footerAlign="center" - footerStyle={{ marginBottom: 16 }} - > - - - </Row> - - <Row justify="center"> - <Text - style={{ - textAlign: 'center', - width: '404px', - }} - children={Languages.t('components.locked_features.locked_only_office_popup.text')} - /> - </Row> - </ObjectModal> -); diff --git a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedGuestsPopup/LockedGuestsPopup.tsx b/twake/frontend/src/app/components/LockedFeaturesComponents/LockedGuestsPopup/LockedGuestsPopup.tsx deleted file mode 100644 index b80fec953a..0000000000 --- a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedGuestsPopup/LockedGuestsPopup.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { Button, Row, Typography } from 'antd'; -import ObjectModal from 'app/components/ObjectModal/ObjectModal'; -import React from 'react'; -import ModalManager from 'app/components/Modal/ModalManager'; -import Languages from 'services/languages/languages'; -import Emojione from 'app/components/Emojione/Emojione'; - -type PropsType = { - companySubscriptionUrl: string; -}; - -const { Text } = Typography; -const LockedGuestsPopup = ({ companySubscriptionUrl }: PropsType): JSX.Element => { - const onClickLearnMore = () => window.open(companySubscriptionUrl, 'blank'); - const onClickSkipForNow = () => ModalManager.close(); - - return ( - <ObjectModal - titleCenter - titleLevel={2} - title={ - <div - style={{ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - }} - > - {Languages.t('components.locked_features.locked_guests_popup.title')} - <Emojione type=":lock:" s128 /> - </div> - } - style={{ padding: 32 }} - hideFooterDivider - footerAlign="center" - footerStyle={{ marginBottom: 16 }} - footer={ - <div - style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 32 }} - > - <Button type="primary" size="large" onClick={onClickLearnMore}> - {Languages.t('components.locked_features.locked_guests_popup.learn_more_button')} - </Button> - <Typography.Text style={{ margin: '16px 0 ' }} strong> - {Languages.t('components.locked_features.locked_guests_popup.or')} - </Typography.Text> - <Button type="ghost" style={{ height: 36, width: 163 }} onClick={onClickSkipForNow}> - {Languages.t('components.locked_features.locked_guests_popup.skip_for_now_button')} - </Button> - </div> - } - > - <Row justify="center" style={{ margin: '12px 0 32px 0', height: '25px' }}> - <Typography.Title - level={3} - style={{ - textAlign: 'center', - margin: 0, - }} - > - {Languages.t('components.locked_features.locked_guests_popup.subtitle')} - </Typography.Title> - </Row> - - <Row justify="center"> - <Typography.Text - style={{ - textAlign: 'center', - width: '404px', - }} - > - {Languages.t('components.locked_features.locked_guests_popup.description')} - </Typography.Text> - </Row> - </ObjectModal> - ); -}; - -export default LockedGuestsPopup; diff --git a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedHistoryBanner/LockedHistoryBanner.tsx b/twake/frontend/src/app/components/LockedFeaturesComponents/LockedHistoryBanner/LockedHistoryBanner.tsx deleted file mode 100644 index 53ff8fc5e0..0000000000 --- a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedHistoryBanner/LockedHistoryBanner.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import { Typography, Button } from 'antd'; -import Banner from 'app/components/Banner/Banner'; -import Emojione from 'app/components/Emojione/Emojione'; -import Languages from 'services/languages/languages'; -import './LockedHistoryBanner.scss'; -import InitService from 'app/services/InitService'; - -const { Title, Text } = Typography; -const LockedHistoryBanner = (): JSX.Element => { - const onClickBtn = () => - window.open( - InitService.server_infos?.configuration?.accounts?.console?.company_subscription_url || '', - 'blank', - ); - - return ( - <Banner - type="ghost" - height={135} - className="locked-history-banner" - contentColumnStyle={{ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - height: '100%', - width: '380px', - }} - > - <div className="title-container"> - <Emojione type=":rocket:" s64 /> - <Title level={5} className="title"> - {Languages.t('components.locked_features.locked_history_banner.title')} - -
- - {Languages.t('components.locked_features.locked_history_banner.description')} - - - - ); -}; - -export default LockedHistoryBanner; diff --git a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedOnlyOfficePopup/LockedOnlyOfficePopup.tsx b/twake/frontend/src/app/components/LockedFeaturesComponents/LockedOnlyOfficePopup/LockedOnlyOfficePopup.tsx deleted file mode 100644 index bfcd88199e..0000000000 --- a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedOnlyOfficePopup/LockedOnlyOfficePopup.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import ObjectModal from 'app/components/ObjectModal/ObjectModal'; -import { Button, Row, Typography } from 'antd'; -import ModalManager from 'app/components/Modal/ModalManager'; -import Languages from 'services/languages/languages'; -import InitService from 'app/services/InitService'; - -type PropsType = { - pricingPlanUrl: string; -}; - -const { Title, Text } = Typography; -export default () => ( - - - - {Languages.t('components.locked_features.locked_guests_popup.or')} - - -
- } - hideFooterDivider - footerAlign="center" - footerStyle={{ marginBottom: 16 }} - > - - - </Row> - - <Row justify="center"> - <Text - style={{ - textAlign: 'center', - width: '404px', - }} - children={Languages.t('components.locked_features.locked_only_office_popup.text')} - /> - </Row> - </ObjectModal> -); diff --git a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedWorkspacePopup/LockedWorkspacePopup.tsx b/twake/frontend/src/app/components/LockedFeaturesComponents/LockedWorkspacePopup/LockedWorkspacePopup.tsx deleted file mode 100644 index 6cedc06958..0000000000 --- a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedWorkspacePopup/LockedWorkspacePopup.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import ObjectModal from 'app/components/ObjectModal/ObjectModal'; -import { Button, Row, Typography } from 'antd'; -import ModalManager from 'app/components/Modal/ModalManager'; -import Languages from 'services/languages/languages'; -import InitService from 'app/services/InitService'; - -const { Title, Text } = Typography; -export default () => ( - <ObjectModal - titleCenter - titleLevel={2} - title={Languages.t('components.locked_features.locked_workspace_popup.title')} - titleTypographyStyle={{ textAlign: 'center', marginBottom: 32 }} - style={{ padding: 32 }} - contentStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }} - footer={ - <div - style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 32 }} - > - <Button - type="primary" - size="large" - style={{ marginTop: 8 }} - onClick={() => - window.open( - InitService.server_infos?.configuration?.accounts?.console - ?.company_subscription_url || '', - 'blank', - ) - } - > - {Languages.t('components.locked_features.locked_guests_popup.learn_more_button')} - </Button> - <Text style={{ margin: '16px 0 ' }} strong> - {Languages.t('components.locked_features.locked_guests_popup.or')} - </Text> - <Button - type="ghost" - style={{ height: 36, width: 163 }} - onClick={() => ModalManager.closeAll()} - > - {Languages.t('components.locked_features.locked_guests_popup.skip_for_now_button')} - </Button> - </div> - } - hideFooterDivider - footerAlign="center" - footerStyle={{ marginBottom: 16 }} - > - <Row justify="center" align="middle" className="bottom-margin"> - <Title - level={3} - children={Languages.t('components.locked_features.locked_workspace_popup.subtitle')} - style={{ - textAlign: 'center', - margin: 0, - }} - /> - </Row> - - <Row justify="center"> - <Text - style={{ - textAlign: 'center', - width: '404px', - }} - children={Languages.t('components.locked_features.locked_workspace_popup.text')} - /> - </Row> - </ObjectModal> -); diff --git a/twake/frontend/src/app/components/MainPlus/MainPlus.js b/twake/frontend/src/app/components/MainPlus/MainPlus.js deleted file mode 100755 index 4e77bf924d..0000000000 --- a/twake/frontend/src/app/components/MainPlus/MainPlus.js +++ /dev/null @@ -1,24 +0,0 @@ -import React, { Component } from 'react'; -import Icon from 'components/Icon/Icon.js'; -import Menu from 'components/Menus/Menu.js'; -import './MainPlus.scss'; - -export default class MainPlus extends Component { - constructor(props) { - super(props); - } - render() { - if (this.props.onClick) { - return ( - <div className="main_plus_button" onClick={this.props.onClick}> - <Icon type="plus" className="m-icon-small" /> - </div> - ); - } - return ( - <Menu menu={this.props.menu} className="main_plus_button" position={'top'}> - <Icon type="plus" className="m-icon-small" /> - </Menu> - ); - } -} diff --git a/twake/frontend/src/app/components/Member/UserParts.tsx b/twake/frontend/src/app/components/Member/UserParts.tsx deleted file mode 100644 index 005eaeec8e..0000000000 --- a/twake/frontend/src/app/components/Member/UserParts.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React from 'react'; -import { Avatar, Badge, Tag } from 'antd'; -import { DashOutlined } from '@ant-design/icons'; -import { User } from 'react-feather'; -import Languages from 'services/languages/languages'; -import RouterServices from 'services/RouterService'; -import { UserType } from 'app/models/User'; -import UserService from 'services/user/UserService'; -import Collections from 'services/Depreciated/Collections/Collections'; -import UsersService from 'services/user/UserService'; -import UserIcon from 'components/User/User'; - -type UserPartsType = { - avatar: JSX.Element; - name: string; - users: UserType[]; - companyRole: JSX.Element; -}; - -type PropsType = { - usersIds: string[]; - keepMyself?: boolean; - displayOnline?: boolean; - max?: number; - size?: number; -}; - -export const getUserParts = (props: PropsType): UserPartsType => { - const { companyId } = RouterServices.getStateFromRoute(); - const avatarSize = props.size || 20; - - let channelMembers = (props.usersIds || []).filter( - e => - props.keepMyself || - (props.usersIds.length || 0) === 1 || - e !== UsersService.getCurrentUserId(), - ); - channelMembers = channelMembers.filter((e, i) => channelMembers.indexOf(e) === i); - - let avatar: JSX.Element = ( - <Avatar size={avatarSize} icon={<User size={12} style={{ margin: 4 }} />} /> - ); - let channelName: string[] = []; - - let users: UserType[] = []; - - channelMembers?.map(userId => users.push(Collections.get('users').find(userId))); - - if (channelMembers?.length === 1) { - const avatarSrc = users[0]?.id ? <UserIcon user={users[0]} withStatus={props.displayOnline} size={avatarSize}/> : UserService.getThumbnail(users[0]); - avatar = ( - <Badge count={0} size="default" dot offset={[-4, 16]}> - <Avatar style={{overflow: 'visible'}} size={avatarSize} src={avatarSrc} /> - </Badge> - ); - channelName = [UserService.getFullName(users[0])]; - } else if (channelMembers?.length || 0 > 1) { - avatar = ( - <Avatar.Group - maxCount={(props.max || 3) + 1} - maxStyle={{ - color: '#FFFFFF', - backgroundColor: `var(--grey-dark)`, - width: avatarSize, - height: avatarSize, - display: 'flex', - alignItems: 'center', - }} - > - {users - .filter((_, i) => i < (props.max || 3)) - .map(member => { - channelName.push(UserService.getFullName(member)); - return ( - member && ( - <Avatar - key={member.id} - size={avatarSize} - src={UserService.getThumbnail(member)} - /> - ) - ); - })} - {users.length > (props.max || 3) && ( - <Avatar - size={avatarSize} - style={{ backgroundColor: 'var(--grey-dark)' }} - icon={<DashOutlined />} - /> - )} - </Avatar.Group> - ); - } - - const roleOriginalString = UserService.getUserRole(users[0], companyId); - const companyRoleObject = getCurrentCompanyRoleObject(roleOriginalString); - const companyRole = - companyRoleObject.name !== 'unknown' ? ( - <Tag color={companyRoleObject.color}>{companyRoleObject.name}</Tag> - ) : ( - <></> - ); - - const shouldDisplayNotShowedUsersCount = users.length > (props.max || 3); - const notShowedUsersCount = users.length - (props.max || 3) + 1; /* myself */ - const name = `${channelName.join(', ')}${ - shouldDisplayNotShowedUsersCount - ? Languages.t('components.member.user_parts.and_more_user_text', [notShowedUsersCount]) - : '' - }`; - - return { - avatar, - name, - users, - companyRole, - }; -}; - -const getCurrentCompanyRoleObject = (role: string) => { - switch (role) { - case 'admin': - return { - color: 'var(--red)', - name: Languages.t('general.user.role.company.admin'), - }; - case 'member': - return { - color: 'var(--primary)', - name: Languages.t('general.user.role.company.member'), - }; - case 'guest': - return { - color: 'var(--grey-dark)', - name: Languages.t('general.user.role.company.guest'), - }; - default: - return { name: 'unknown' }; - } -}; diff --git a/twake/frontend/src/app/components/Menus/Menu.js b/twake/frontend/src/app/components/Menus/Menu.js deleted file mode 100755 index 92357528d7..0000000000 --- a/twake/frontend/src/app/components/Menus/Menu.js +++ /dev/null @@ -1,107 +0,0 @@ -import React, { Component } from 'react'; - -import MenusManager from 'app/components/Menus/MenusManager.js'; - -/* - One menu -*/ -export default class Menu extends React.Component { - /* - props = { - menu : menu object ex. {type:"menu", text:"Un menu", icon:"list"}, - {type:"menu", text:"Un menu avec sous menu", icon:"grid", submenu: [ - {text:"Sub menu 4", icon: "search"}, - {text:"Sub menu 5", icon: "search"}, - {text:"Sub menu 6", icon: "search"} - ]}, - {type:"menu", text:"Un menu avec sous menu", icon:"grid", submenu: [ - {type:"react-element", text:"Sub menu 6", icon: "search", reactElement:<div className="hello">salut</div>} - ]}, - {type:"separator"}, - {type:"text", text:"Du texte"} - {type:"react-element", reactElement: <Element />} - } - */ - - static closeAll() { - MenusManager.closeMenu(); - } - - constructor(props) { - super(); - this.state = { - menus_manager: MenusManager, - }; - MenusManager.addListener(this); - } - componentWillUnmount() { - if (this.props.onClose && this.open) { - this.props.onClose(); - } - MenusManager.removeListener(this); - } - openMenuFromParent(menu, rect, position) { - MenusManager.openMenu(menu, rect, position); - } - openMenu(evt) { - this.open = true; - evt.preventDefault(); - evt.stopPropagation(); - var elementRect = window.getBoundingClientRect(this.container); - elementRect.x = elementRect.x || elementRect.left; - elementRect.y = elementRect.y || elementRect.top; - this.previous_menus_id = MenusManager.openMenu( - this.props.menu, - elementRect, - this.props.position, - ); - if (this.props.onOpen) this.props.onOpen(); - } - shouldComponentUpdate(nextProps, nextState) { - if (nextProps.menu != this.props.menu && this.open) { - this.setState({}); - } - - if ( - (this.state.menus_manager.menus.length == 0 && this.previous_menus_number > 0) || - this.state.menus_manager.last_opened_id != this.previous_menus_id - ) { - if (this.open && this.props.onClose) { - this.props.onClose(); - } - this.open = false; - } - if (this.previous_menus_number != this.state.menus_manager.menus.length) { - this.previous_menus_number = this.state.menus_manager.menus.length; - } - - if (this.props.style !== nextProps.style || this.props.className !== nextProps.className) { - return true; - } - - return false; - } - render() { - return ( - <div - ref={node => (this.container = node)} - style={this.props.style} - onClick={evt => { - if (this.props.toggle) { - if (!this.open) { - this.openMenu(evt); - } else { - MenusManager.closeMenu(); - this.props.onClose && this.props.onClose(); - } - } else { - this.openMenu(evt); - } - }} - className={this.props.className} - > - {this.props.children} - </div> - ); - } -} diff --git a/twake/frontend/src/app/components/Menus/MenuComponent.js b/twake/frontend/src/app/components/Menus/MenuComponent.js deleted file mode 100755 index 69dd8d806d..0000000000 --- a/twake/frontend/src/app/components/Menus/MenuComponent.js +++ /dev/null @@ -1,143 +0,0 @@ -import React, { Component } from 'react'; - -import Icon from 'components/Icon/Icon.js'; -import Emojione from 'components/Emojione/Emojione'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import './Menu.scss'; - -/* - One menu -*/ -export default class MenuComponent extends React.Component { - constructor(props) { - super(); - this.state = { - menus_manager: MenusManager, - }; - MenusManager.addListener(this); - } - componentWillUnmount() { - MenusManager.removeListener(this); - } - openSubMenu(dom_element, menu, level) { - var elementRect = window.getBoundingClientRect(dom_element); - elementRect.x = elementRect.x || elementRect.left; - elementRect.y = elementRect.y || elementRect.top; - MenusManager.openSubMenu(menu, elementRect, level); - } - closeSubMenu(level) { - MenusManager.closeSubMenu(level); - } - hoverMenu(dom_element, item) { - if (item.submenu && !item.submenu_replace) { - this.last_hovered = item; - this.openSubMenu(dom_element, item.submenu, this.props.level || 0); - } else { - this.closeSubMenu(this.props.level || 0); - } - } - clickMenu(dom_element, item, evt) { - if(Date.now() - this.props.openAt < 200 ){ - // When a menu is open and another one opens above it, you have to block the buttons for a while. Otherwise, the hovered option of the new menu will be clicked - return; - } - if (item.submenu_replace) { - MenusManager.openMenu(item.submenu, { x: evt.clientX, y: evt.clientY }, 'center'); - return; - } - if (item.onClick) { - var res = item.onClick(evt); - if (res !== false) { - MenusManager.closeMenu(); - } - } - } - render() { - return ( - <div - ref={node => (this.original_menu = node)} - className={ - 'menu-list ' + (this.props.withFrame ? 'as_frame ' : '') + this.props.animationClass - } - > - {(this.props.menu || []) - .filter(item => item && !item.hide) - .map((item, index) => { - if (item.type == 'separator') { - return <div key={'menu_' + index} className="menu-separator" />; - } else if (item.type == 'title') { - return ( - <div key={'menu_' + index} className={'menu-title ' + item.className}> - {item.text} - </div> - ); - } else if (item.type == 'text') { - return ( - <div - key={'menu_' + index} - ref={node => (item.ref = node)} - className={'menu-text ' + item.className} - onMouseEnter={evt => { - this.hoverMenu(item.ref, item); - }} - > - {item.text} - </div> - ); - } else if (item.type == 'react-element') { - return ( - <div - key={'menu_' + index} - className={'menu-custom ' + item.className} - onClick={item.onClick} - > - {typeof item.reactElement == 'function' - ? item.reactElement(this.props.level) - : item.reactElement} - </div> - ); - } else { - return ( - <div - key={'menu_' + index} - ref={node => (item.ref = node)} - className={ - 'menu ' + - item.className + - ' ' + - (this.state.menus_manager.max_level > this.props.level && - this.last_hovered == item - ? 'hovered ' - : '') + - (item.selected ? 'selected ' : '') - } - onMouseEnter={evt => { - this.hoverMenu(item.ref, item); - }} - onClick={evt => { - this.clickMenu(item.ref, item, evt); - }} - > - {item.icon && ( - <div className="icon"> - {typeof item.icon === 'string' ? <Icon type={item.icon} /> : item.icon} - </div> - )} - {item.emoji && ( - <div className="icon"> - <Emojione type={item.emoji} /> - </div> - )} - <div className="text">{item.text}</div> - <div className="more"> - {item.rightIcon && <Icon type={item.rightIcon} />} - {item.submenu && !item.submenu_replace && <Icon type="angle-right" />} - </div> - </div> - ); - } - })} - </div> - ); - } -} diff --git a/twake/frontend/src/app/components/Menus/MenusBodyLayer.js b/twake/frontend/src/app/components/Menus/MenusBodyLayer.js deleted file mode 100755 index 94b9effd53..0000000000 --- a/twake/frontend/src/app/components/Menus/MenusBodyLayer.js +++ /dev/null @@ -1,225 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; - -import MenusManager from 'app/components/Menus/MenusManager.js'; -import MenuComponent from './MenuComponent.js'; -import OutsideClickHandler from 'react-outside-click-handler'; - -/* - Where the menu will be displayed, this component should be in app.js (menus should be over all elements of the page) -*/ -export default class MenusBodyLayer extends React.Component { - constructor(props) { - super(); - this.state = { - menus_manager: MenusManager, - }; - this.menus_dom = null; - this.menu_observer = {}; - MenusManager.addListener(this); - this.outsideMenuListener = this.outsideMenuListener.bind(this); - this.outsideMenuListenerUp = this.outsideMenuListenerUp.bind(this); - - this.lastUpdatePosition = {}; - this.indexUpdatePosition = {}; - } - outsideMenuListener() { - //NOT WORKING - if ( - MenusManager.menus.length > 0 && - MenusManager.menus[MenusManager.menus.length - 1].allowClickOut - ) { - this.will_close_on_up = true; - } else { - this.will_close_on_up = false; - } - } - outsideMenuListenerUp() { - //NOT WORKING - if ( - MenusManager.menus.length > 0 && - MenusManager.menus[MenusManager.menus.length - 1].allowClickOut - ) { - if (this.will_close_on_up) { - MenusManager.closeMenu(); - } - } else { - this.will_close_on_up = false; - } - } - componentWillMount() { - if (!document.getElementById('context-menu-layer')) { - const div = document.createElement('div'); - div.setAttribute('id', 'context-menu-layer'); - document.body.appendChild(div); - } - } - componentWillUnmount() { - MenusManager.removeListener(this); - document.removeEventListener('mousedown', this.outsideClickListener); - document.removeEventListener('mouseup', this.outsideClickListenerUp); - - Object.keys(this.menu_observer).forEach(index => { - this.menu_observer[index].disconnect(); - }); - } - componentDidMount() { - var element = this.menus_dom; - this.outsideClickListener = event => { - if (!element.contains(event.target) && document.contains(event.target)) { - this.outsideMenuListener(); - } - }; - this.outsideClickListenerUp = event => { - if (!element.contains(event.target) && document.contains(event.target)) { - this.outsideMenuListenerUp(); - } - }; - document.addEventListener('mousedown', this.outsideClickListener); - document.addEventListener('mouseup', this.outsideClickListenerUp); - } - fixMenuPosition(node, item, index) { - if (!node) { - return; - } - - if (this.lastUpdatePosition[item.id] !== parseInt(new Date().getTime() / 1000)) { - this.lastUpdatePosition[item.id] = parseInt(new Date().getTime() / 1000); - this.indexUpdatePosition[item.id] = 0; - } else if (this.indexUpdatePosition[item.id] > 2) { - return; - } - this.indexUpdatePosition[item.id]++; - - if (this.menu_observer[index]) { - this.menu_observer[index].disconnect(); - } - - var config = { childList: true, subtree: true }; - this.menu_observer[index] = new MutationObserver(() => { - this.fixMenuPosition(node, item); - }); - this.menu_observer[index].observe(node, config); - - var nr = window.getBoundingClientRect(node); - nr.x = nr.x || nr.left; - nr.y = nr.y || nr.top; - var rect = JSON.parse(JSON.stringify(nr || {})); - rect.height = Math.max(node.offsetHeight, rect.height); - rect.bottom = rect.height + rect.y; - - var max_bottom = document.documentElement.clientHeight; - if (item.positionType === 'top') { - max_bottom = item.position.y; - } - - //Top - if (rect.top < 5 || (rect.top > 10 && item.position.marginTop > 0)) { - item.position.marginTop = Math.max(0, (item.position.marginTop || 0) - rect.top + 5); - MenusManager.notify(); - } - - //Bottom - if (item.position.marginTop === undefined || item.position.marginTop < 0) { - //Else we are on the top top - if ( - rect.bottom > Math.min(document.documentElement.clientHeight, max_bottom) - 5 || - (rect.bottom < Math.min(document.documentElement.clientHeight, max_bottom) - 10 && - item.position.marginTop < 0) - ) { - item.position.marginTop = Math.min( - 0, - (item.position.marginTop || 0) - - (rect.bottom - Math.min(document.documentElement.clientHeight, max_bottom) + 5), - ); - MenusManager.notify(); - } - } - - //Left - if (rect.left < 5 || (rect.left > 10 && item.position.marginLeft > 0)) { - item.position.marginLeft = Math.max(0, (item.position.marginLeft || 0) - rect.left + 5); - MenusManager.notify(); - } - //Right - else if ( - rect.right > document.documentElement.clientWidth - 5 || - (rect.right < document.documentElement.clientWidth - 10 && item.position.marginLeft < 0) - ) { - item.position.marginLeft = Math.min( - 0, - (item.position.marginLeft || 0) - (rect.right - document.documentElement.clientWidth + 5), - ); - MenusManager.notify(); - } - } - shouldComponentUpdate(nextProps, nextState) { - if (nextState.menus_manager.willClose !== this.willClose) { - this.willClose = nextState.menus_manager.willClose; - return true; - } - if (this.state.menus_manager.menus.length > 0 || this.last_menu_length > 0) { - this.last_menu_length = this.state.menus_manager.menus.length; - return true; - } - return false; - } - render() { - return ReactDOM.createPortal( - <OutsideClickHandler - onOutsideClick={() => { - MenusManager.closeMenu(); - }} - > - <div ref={node => (this.menus_dom = node)}> - {this.state.menus_manager.menus.map((item, i) => { - var menu = ( - <OutsideClickHandler - key={item.id} - onOutsideClick={() => { - if (i === this.state.menus_manager.menus.length - 1) { - MenusManager.closeSubMenu(item.level - 1); - } - }} - > - <div - ref={node => this.fixMenuPosition(node, item, i)} - style={{ - zIndex: 1050, - position: 'absolute', - transform: item.positionType === 'bottom' ? '' : 'translateY(-50%)', - left: item.position.x, - top: item.position.y, - marginTop: item.position.marginTop, - marginLeft: item.position.marginLeft, - }} - > - <MenuComponent - withFrame - menu={item.menu} - openAt={item.openAt} - level={item.level} - animationClass={ - this.state.menus_manager.willClose || item.willClose - ? 'fade_out' - : item.level === 0 || item.positionType - ? item.positionType === 'bottom' - ? 'skew_in_bottom_nobounce' - : item.left - ? 'skew_in_left_nobounce' - : 'skew_in_right_nobounce' - : 'fade_in' - } - /> - </div> - </OutsideClickHandler> - ); - - return menu; - })} - </div> - </OutsideClickHandler>, - document.getElementById('context-menu-layer'), - ); - } -} diff --git a/twake/frontend/src/app/components/Menus/MenusManager.js b/twake/frontend/src/app/components/Menus/MenusManager.js deleted file mode 100755 index adf1b79b3d..0000000000 --- a/twake/frontend/src/app/components/Menus/MenusManager.js +++ /dev/null @@ -1,179 +0,0 @@ -import Observable from 'app/services/Depreciated/observable.js'; -import Number from 'services/utils/Numbers'; -import Globals from 'services/Globals'; - -/** - * Menus manager service, choose where to generate menu - */ -class MenusManager extends Observable { - constructor() { - super(); - this.setObservableName('menus_manager'); - - window.menusService = this; - - this.menus = []; - this.lastOpen = 0; - this.willClose = false; - this.max_level = 0; - - var that = this; - Globals.window.addEventListener('keydown', function (evt) { - evt = evt || window.event; - var isEscape = false; - if ('key' in evt) { - isEscape = evt.key === 'Escape' || evt.key === 'Esc'; - } else { - isEscape = evt.keyCode === 27; - } - if (isEscape) { - that.closeMenu(); - } - }); - - this.closeMenu.bind(this); - this.openMenu.bind(this); - } - closeMenu() { - if (this.menus.length === 0) { - this.willClose = false; - return; - } - - if (new Date().getTime() - this.lastOpen < 500) { - return; - } - this.willClose = true; - - if (this.closeMenuTimeout) { - clearTimeout(this.closeMenuTimeout); - } - this.closeMenuTimeout = setTimeout(() => { - this.willClose = false; - this.menus = []; - this.notify(); - }, 200); - - this.notify(); - } - openMenu(menu, domRect, positionType, options) { - this.menus = []; - - if (this.closeMenuTimeout) { - this.willClose = false; - clearTimeout(this.closeMenuTimeout); - } - - if (!options) { - options = {}; - } - - var position = this.bestPosition(domRect, positionType, { margin: options.margin || 0 }); - - this.menus.push({ - menu: menu, - positionType: positionType, - position: position, - left: position.left, - openAt: Date.now(), - level: 0, - id: Number.unid(), - allowClickOut: options.allowClickOut !== undefined ? options.allowClickOut : true, - }); - this.last_opened_id = Number.unid(); - this.notify(); - this.lastOpen = new Date().getTime(); - - return this.last_opened_id; - } - openSubMenu(menu, domRect, level, positionType) { - this.max_level = level + 1; - this.closeSubMenu(level); - var position = this.bestPosition(domRect, positionType); - this.menus.push({ - menu: menu, - positionType: positionType, - position: position, - left: position.left, - openAt: Date.now(), - level: level + 1, - id: Number.unid(), - }); - - this.notify(); - } - closeSubMenu(level) { - this.max_level = level; - this.menus.forEach(item => { - if (item.level > level) { - item.willClose = true; - } - }); - this.notify(); - setTimeout(() => { - var new_menus = []; - this.menus.forEach(item => { - if (!(item.level > level && item.willClose)) { - new_menus.push(item); - } - }); - this.menus = new_menus; - this.notify(); - }, 200); - } - - bestPosition(rect, position, options) { - if (Globals.isReactNative) { - return {}; - } - - options = options || {}; - options.margin = options.margin || 0; - - rect = { - left: rect.left - options.margin, - x: rect.x - options.margin, - top: rect.top - options.margin, - y: rect.y - options.margin, - right: rect.right + options.margin, - bottom: rect.bottom + options.margin, - width: rect.width + 2 * options.margin, - height: rect.height + 2 * options.margin, - }; - - var x = rect.right || rect.x; - var y = rect.y; - - if (position === 'top' || position === 'bottom' || position === 'center') { - x = rect.x; - y = rect.bottom || rect.y; - if (position === 'top') { - y = rect.top || rect.y; - } - - return { - x: x + (rect.width || 0) / 2 - 100, - y: y, - left: false, - }; - } - - var left = false; - if (rect.right + 200 > document.documentElement.clientWidth) { - x = (rect.left || rect.x) - 200; - left = true; - } - if (x < 0) { - x = 0; - left = false; - } - - return { - x: x, - y: y + (rect.height || 0) / 2, - left: left, - }; - } -} - -export default new MenusManager(); diff --git a/twake/frontend/src/app/components/Modal/ModalComponent.tsx b/twake/frontend/src/app/components/Modal/ModalComponent.tsx deleted file mode 100755 index 455e4ad065..0000000000 --- a/twake/frontend/src/app/components/Modal/ModalComponent.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useEffect, useMemo } from 'react'; -import { Modal } from 'antd'; -import './ModalComponent.scss'; -import ModalManager from 'app/components/Modal/ModalManager'; - -let component: any = null; -export default () => { - const open = ModalManager.useWatcher(() => ModalManager.isOpen()); - - const eventClose = useMemo( - () => (evt: any) => { - if (evt.keyCode === 27 && ModalManager.canClose()) { - close(); - } - }, - [], - ); - - const close = () => { - if (ModalManager.canClose()) { - ModalManager.close(); - } - }; - - /* eslint-disable react-hooks/exhaustive-deps */ - useEffect(() => { - document.addEventListener('keydown', eventClose); - return () => { - document.removeEventListener('keydown', eventClose); - }; - }, []); - /* eslint-enable react-hooks/exhaustive-deps */ - - component = ModalManager.getComponent() || component; - - return ( - <Modal - onCancel={close} - centered - closable={false} - title={null} - visible={open} - footer={null} - destroyOnClose={true} - > - {component} - </Modal> - ); -}; diff --git a/twake/frontend/src/app/components/Modal/ModalManager.ts b/twake/frontend/src/app/components/Modal/ModalManager.ts deleted file mode 100755 index 6e7d9edcc4..0000000000 --- a/twake/frontend/src/app/components/Modal/ModalManager.ts +++ /dev/null @@ -1,76 +0,0 @@ -import Observable from 'app/services/Observable/Observable'; -import MenusManager from 'app/components/Menus/MenusManager.js'; - -class ModalManager extends Observable { - static service: ModalManager = new ModalManager(); - private component: any[] = []; - private popupStates: any = {}; - private position: any = null; - private mountedComponent: any = null; - private closing: boolean = false; - private creationTimeout: any = null; - - updateHighlight(highlight: any) { - if (this.position) this.position.highlight = highlight; - this.notify(); - } - - open(component: any, position: any, canClose?: boolean, clearState?: any) { - this.close(); - - this.mountedComponent = null; - - this.creationTimeout && clearTimeout(this.creationTimeout); - this.creationTimeout = setTimeout(() => { - this.component = []; - this.position = position || {}; - MenusManager.closeMenu(); - if (clearState) { - delete this.popupStates[clearState]; - } - this.component.push({ component: component, canClose: canClose !== false }); - this.notify(); - }, 100); - } - - isOpen() { - return this.component.length > 0; - } - - close() { - if (this.closing) { - return false; - } - if (this.isOpen()) { - this.closing = true; - (this.mountedComponent || {}).onMediumPopupClose && - this.mountedComponent.onMediumPopupClose(); - - this.mountedComponent = null; - this.component.splice(-1, 1); - this.notify(); - this.closing = false; - } - } - closeAll() { - if (this.isOpen()) { - (this.mountedComponent || {}).onMediumPopupClose && - this.mountedComponent.onMediumPopupClose(); - - this.mountedComponent = null; - this.component = []; - this.notify(); - } - } - canClose() { - if (this.isOpen()) { - return this.component[this.component.length - 1].canClose; - } - return null; - } - getComponent() { - return this.component[this.component.length - 1]?.component || ''; - } -} - -export default ModalManager.service; diff --git a/twake/frontend/src/app/components/NewVersion/NewVersionComponent.tsx b/twake/frontend/src/app/components/NewVersion/NewVersionComponent.tsx deleted file mode 100644 index c62b686de8..0000000000 --- a/twake/frontend/src/app/components/NewVersion/NewVersionComponent.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useMemo, useState } from 'react'; -import { Col, Row, Typography } from 'antd'; - -import Api from 'services/Api'; -import Banner from 'app/components/Banner/Banner'; -import Emojione from 'app/components/Emojione/Emojione'; -import { ConfigurationResource } from 'app/models/Configuration'; -import Languages from 'services/languages/languages'; -import Globals from 'services/Globals'; -import ModalManager from 'app/components/Modal/ModalManager'; -import NewVersionModal from './NewVersionModal'; -import { ServerInfoType } from 'app/services/InitService'; - -let lastScrape: number = 0; - -const NewVersionComponent = (): JSX.Element => { - const [displayBanner, setDisplayBanner] = useState<boolean>(false); - - const compareVersion: (v1: string, v2: string) => number = (v1: string, v2: string) => { - const toNumber: (v: string) => number = (v: string) => { - const a = v.split('.').map((s: string) => parseInt(s.replace(/[^0-9]/g, ''))); - return 1000000 * (1000 * a[0] + a[1]) + a[2]; - }; - return toNumber(v1) - toNumber(v2); - }; - - - - useMemo(() => { - - const getConfiguration = async () => { - if (new Date().getTime() - lastScrape < 15 * 60 * 1000) { - return; - } - lastScrape = new Date().getTime(); - - const config = await Api.get<ServerInfoType>( - '/internal/services/general/v1/server', - undefined, - false, - { - disableJWTAuthentication: true, - }, - ); - const currentVersion: string = Globals.version.version_detail; - const newestVersion: string = config?.version?.current || ''; - const minimalWebVersion: string = config?.version?.minimal?.web || ''; - - const shouldDisplayModal: boolean = - minimalWebVersion && compareVersion(minimalWebVersion, currentVersion) > 0 ? true : false; - const shouldDisplayBanner: boolean = - newestVersion && compareVersion(newestVersion, currentVersion) > 0 && !shouldDisplayModal - ? true - : false; - - if (shouldDisplayModal) { - return ModalManager.open( - <NewVersionModal />, - { - position: 'center', - size: { width: '600px' }, - }, - false, - ); - } - - if (shouldDisplayBanner) { - return setDisplayBanner(shouldDisplayBanner); - } - }; - - document.addEventListener('visibilitychange', () => { - getConfiguration(); - }); - window.addEventListener('focus', () => { - getConfiguration(); - }); - getConfiguration(); - }, []); - - return ( - <> - {displayBanner && ( - <Banner - height={32} - type="primary" - content={ - <Row align="middle" gutter={[8, 0]}> - <Col> - <b>{Languages.t('components.newversion.new_version_component.row.part_1')}</b>,{' '} - {Languages.t('components.newversion.new_version_component.row.part_2')}{' '} - <Emojione type="rocket" /> - </Col> - <Col> - <Typography.Link - style={{ color: 'var(--white)' }} - underline - onClick={() => window.location.reload()} - > - {Languages.t('components.newversion.new_version_component.link')} - </Typography.Link> - </Col> - </Row> - } - closable - onClose={() => setDisplayBanner(false)} - /> - )} - </> - ); -}; -export default NewVersionComponent; diff --git a/twake/frontend/src/app/components/NewVersion/NewVersionModal.tsx b/twake/frontend/src/app/components/NewVersion/NewVersionModal.tsx deleted file mode 100644 index 6f125af4bf..0000000000 --- a/twake/frontend/src/app/components/NewVersion/NewVersionModal.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import ObjectModal from '../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import Emojione from '../Emojione/Emojione'; -import { Button } from 'antd'; - -const NewVersionModal = () => { - const onClickBtn = () => { - return window.location.reload(); - }; - - return ( - <ObjectModal - title={ - <> - {Languages.t('components.newversion.new_version_modal.title')} <Emojione type="rocket" /> - </> - } - footer={ - <Button type="primary" onClick={onClickBtn}> - {Languages.t('scenes.app.header.disconnected.reload')} - </Button> - } - > - <div className="x-margin"> - <b>{Languages.t('components.newversion.new_version_component.row.part_1')}</b>,{' '} - {Languages.t('components.newversion.new_version_component.row.part_2')} - </div> - </ObjectModal> - ); -}; - -export default NewVersionModal; diff --git a/twake/frontend/src/app/components/ObjectModal/DeprecatedObjectModal.js b/twake/frontend/src/app/components/ObjectModal/DeprecatedObjectModal.js deleted file mode 100755 index 9e67de3633..0000000000 --- a/twake/frontend/src/app/components/ObjectModal/DeprecatedObjectModal.js +++ /dev/null @@ -1,118 +0,0 @@ -import React, { Component } from 'react'; -import Icon from 'components/Icon/Icon.js'; -import PerfectScrollbar from 'react-perfect-scrollbar'; -import Tabs from 'components/Tabs/Tabs.js'; -import './DeprecatedObjectModal.scss'; -import { Divider } from 'antd'; - -export class ObjectModalTitle extends Component { - render() { - return ( - <div className={'modal_title ' + this.props.className} style={this.props.style}> - {this.props.children} - </div> - ); - } -} -//ObjectModalSeparator -export class ObjectModalSeparator extends Component { - render() { - return <div className="separator"></div>; - } -} -//ObjectModalSectionTitle -export class ObjectModalSectionTitle extends Component { - render() { - return ( - <div - style={{ - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'space-between', - marginBottom: this.props.smallMargin ? '16px' : '', - }} - > - <b>{this.props.title || this.props.children}</b> - <div>{this.props.action}</div> - </div> - ); - } -} - -// ObjectModalFormTitle -export class ObjectModalFormTitle extends Component { - render() { - return ( - <div className={'section_title ' + this.props.className} style={this.props.style}> - {this.props.icon && <Icon type={this.props.icon} className="m-icon-small" />} - <span>{this.props.name}</span> - </div> - ); - } -} - -export class ObjectModal extends Component { - constructor(props) { - super(); - this.state = {}; - } - render() { - return ( - <div className={'object_modal ' + this.props.className}> - <div className="top_right_buttons"> - {this.props.onEdit && ( - <div className="square_button" onClick={this.props.onEdit}> - <Icon type="edit-alt" className="m-icon-small" /> - </div> - )} - {this.props.onClose && ( - <div className="square_button" onClick={this.props.onClose}> - <Icon type="times" className="m-icon-small" /> - </div> - )} - </div> - - <div className={!this.props.noCloseButton ? 'title' : ''}>{this.props.title}</div> - - {this.props.tabs && ( - <Tabs - tabs={this.props.tabs.map(item => { - return { - title: item.title || '', - render: ( - <div className="body"> - <PerfectScrollbar options={{ suppressScrollX: true }} component="div"> - {item.render} - </PerfectScrollbar> - </div> - ), - }; - })} - /> - )} - - {!this.props.tabs && ( - <div className="body"> - {!!this.props.noScrollBar && ( - <div className="child-with-margin">{this.props.children}</div> - )} - {!this.props.noScrollBar && ( - <PerfectScrollbar options={{ suppressScrollX: true }} component="div"> - {this.props.children} - </PerfectScrollbar> - )} - </div> - )} - - {this.props.footer && <div className="separator" style={{ marginTop: 0 }} />} - {this.props.footer && ( - <div className="footer bottom-margin"> - <Divider /> - <div className="x-margin">{this.props.footer}</div> - </div> - )} - </div> - ); - } -} diff --git a/twake/frontend/src/app/components/ObjectModal/ObjectModal.tsx b/twake/frontend/src/app/components/ObjectModal/ObjectModal.tsx deleted file mode 100644 index 818a05b9d9..0000000000 --- a/twake/frontend/src/app/components/ObjectModal/ObjectModal.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import React, { FC } from 'react'; - -import classNames from 'classnames'; -import { Divider, Layout, Typography, Col, Row } from 'antd'; - -import ModalManager from 'app/components/Modal/ModalManager'; -import Icon from 'components/Icon/Icon.js'; - -import './ObjectModal.scss'; - -type PropsType = { - title?: string | JSX.Element; - closable?: boolean; - children?: React.Component | JSX.Element | any; - footer?: React.Component | JSX.Element | any; - hideFooterDivider?: boolean; - footerAlign?: 'start' | 'end' | 'center' | 'space-around' | 'space-between' | undefined; - titleCenter?: boolean; - style?: React.CSSProperties; - headerStyle?: React.CSSProperties; - footerStyle?: React.CSSProperties; - titleLevel?: 5 | 1 | 2 | 3 | 4 | undefined; - titleColor?: string; - colTitleStyle?: React.CSSProperties; - contentStyle?: React.CSSProperties; - titleTypographyStyle?: React.CSSProperties; - className?: string; - footerDividerStyle?: React.CSSProperties; -}; - -const { Header, Content, Footer } = Layout; -const ObjectModal: FC<PropsType> = (props: PropsType) => { - return ( - <Layout - className={classNames('modal-layout', props.className)} - hasSider={false} - style={props.style || {}} - > - <Header className="modal-layout-header" style={props.headerStyle || {}}> - <Row justify="space-between" align="middle" className="modal-layout-row" wrap={false}> - {props.titleCenter && <Col style={{ width: 32 }}></Col>} - {props.title && ( - <Col style={props.colTitleStyle}> - <Typography.Title - level={props.titleLevel || 5} - style={{ - margin: 0, - marginTop: props.titleCenter ? 8 : 0, - color: props.titleColor, - ...props.titleTypographyStyle, - }} - > - {props.title} - </Typography.Title> - </Col> - )} - {(props.closable === true && ( - <Col> - <Icon - type="times" - className={`m-icon-small square-button ${ - props.headerStyle?.backgroundColor ? 'red' : '' - }`} - onClick={() => ModalManager.closeAll()} - /> - </Col> - )) || <Col style={{ width: 32 }}></Col>} - </Row> - </Header> - {props.children && <Content style={props.contentStyle}>{props.children}</Content>} - {props.footer && ( - <Footer className="modal-layout-footer"> - {!props.hideFooterDivider && ( - <Divider className="y-margin" style={props.footerDividerStyle} /> - )} - <Row align="middle" justify={props.footerAlign || 'end'}> - <Col - style={{ - marginBottom: props.footerAlign === 'center' ? 54 : 16, - marginRight: !props.footerAlign ? 16 : 0, - ...props.footerStyle, - }} - > - {props.footer} - </Col> - </Row> - </Footer> - )} - </Layout> - ); -}; - -export default ObjectModal; diff --git a/twake/frontend/src/app/components/OnBoarding/AccountStatusComponent.tsx b/twake/frontend/src/app/components/OnBoarding/AccountStatusComponent.tsx deleted file mode 100644 index 88c1314940..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/AccountStatusComponent.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React from 'react'; - -import Banner from 'app/components/Banner/Banner'; -import { Button, Typography } from 'antd'; -import Languages from 'services/languages/languages'; -import ModalManager from 'app/components/Modal/ModalManager'; -import UnverifiedAccount from './popups/UnverifiedAccount'; -import BlockedAccount from './popups/BlockedAccount'; -import UserService from 'services/user/UserService'; -import InitService from 'app/services/InitService'; -import { useCurrentUser } from 'app/state/recoil/hooks/useCurrentUser'; - -const AccountStatusComponent = (): JSX.Element => { - const { user } = useCurrentUser(); - const maxUnverifiedDays = - InitService.server_infos?.configuration?.accounts?.console?.max_unverified_days || 7; - const oneDay = 1000 * 60 * 60 * 24; - const periodLimit = (user?.created_at || 0) + maxUnverifiedDays * oneDay; - const daysLeft = Math.ceil((periodLimit - Date.now()) / oneDay); - - if (!user || InitService.server_infos?.configuration?.accounts?.type !== 'console') { - return <></>; - } - - const showBlockedModal = () => { - if (InitService.server_infos?.configuration?.accounts?.type === 'console') - return ModalManager.open( - <BlockedAccount email={user?.email} />, - { - position: 'center', - size: { width: '600px' }, - }, - false, - ); - }; - - const showUnverifiedModal = () => { - if (InitService.server_infos?.configuration?.accounts?.type === 'console') - return ModalManager.open( - <UnverifiedAccount daysLeft={daysLeft} limit={maxUnverifiedDays} email={user.email} />, - { - position: 'center', - size: { width: '600px' }, - }, - ); - }; - - if (!user.is_verified && daysLeft <= 0) { - showBlockedModal(); - } - - const showBanner = !user.is_verified; - return ( - <> - {showBanner && ( - <Banner - type="important" - content={ - <div style={{ display: 'flex', alignItems: 'center' }}> - <Typography.Title level={5} style={{ marginBottom: 0, color: 'var(--white)' }}> - {Languages.t('components.account_verification_status_sentence', [ - Languages.t('components.account_verication_status_unverified'), - ])} - </Typography.Title> - <Button - style={{ marginLeft: 17, height: 32, color: 'var(--red)' }} - onClick={showUnverifiedModal} - > - {Languages.t('general.verify')} - </Button> - </div> - } - /> - )} - </> - ); -}; - -export default AccountStatusComponent; diff --git a/twake/frontend/src/app/components/OnBoarding/CompanyBillingBanner.tsx b/twake/frontend/src/app/components/OnBoarding/CompanyBillingBanner.tsx deleted file mode 100644 index 737c52ca59..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/CompanyBillingBanner.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import { Row, Typography } from 'antd'; -import Banner from '../Banner/Banner'; -import { CompanyType } from 'app/models/Company'; -import Groups from 'services/workspaces/groups.js'; -import InitService from 'app/services/InitService'; -import Languages from 'services/languages/languages'; -import { AlertTriangle } from 'react-feather'; - -type PropsType = { - companyId: string; -}; - -const { Link } = Typography; -export default ({ companyId }: PropsType): JSX.Element => { - const companySubscriptionUrl = - InitService.server_infos?.configuration.accounts.console?.company_subscription_url || ''; - const userGroups: { [key: string]: CompanyType } = Groups.user_groups; - const currentUserGroup = userGroups[companyId]; - const isCurrentUserAdminOrOwner = - currentUserGroup?.role === 'admin' || currentUserGroup?.role === 'owner'; - - const onClickLink = () => window.open(companySubscriptionUrl, 'blank'); - - const shouldDisplayBanner = currentUserGroup?.plan?.billing?.status === 'warning'; - return shouldDisplayBanner ? ( - <Banner type="important"> - <Row align="middle"> - <AlertTriangle size={24} /> - <div className="small-x-margin"> - {Languages.t( - isCurrentUserAdminOrOwner - ? 'components.on_boarding.company_billing_banner.admin_or_owner_text' - : 'components.on_boarding.company_billing_banner.guest_or_member_text', - )} - </div> - {isCurrentUserAdminOrOwner && ( - <Link onClick={onClickLink}> - {Languages.t('components.on_boarding.company_billing_banner.link')} - </Link> - )} - </Row> - </Banner> - ) : ( - <></> - ); -}; diff --git a/twake/frontend/src/app/components/OnBoarding/CompanyStatusComponent.tsx b/twake/frontend/src/app/components/OnBoarding/CompanyStatusComponent.tsx deleted file mode 100644 index f9e4d4ab77..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/CompanyStatusComponent.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import React, { useEffect } from 'react'; -import ModalManager from 'app/components/Modal/ModalManager'; -import UserService from 'services/user/UserService'; -import WelcomeOnTwake from './popups/WelcomeOnTwake'; -import DepreciatedCollections from 'app/services/Depreciated/Collections/Collections.js'; -import InitService from 'app/services/InitService'; -import RouterServices from 'app/services/RouterService'; -import Groups from 'services/workspaces/groups.js'; -import { CompanyType } from 'app/models/Company'; -import BlockedCompany from './popups/BlockedCompany'; -import useRouterCompany from 'app/state/recoil/hooks/router/useRouterCompany'; -import useRouterWorkspace from 'app/state/recoil/hooks/router/useRouterWorkspace'; - -const CompanyStatusComponent = (): JSX.Element => { - const companyId = useRouterCompany(); - const workspaceId = useRouterWorkspace(); - const user = UserService.getCurrentUser(); - const onboarding: string | null = localStorage.getItem(`onboarding_${companyId}`); - const workspace = DepreciatedCollections.get('workspaces').find(workspaceId); - - useEffect(() => { - if (InitService.server_infos?.configuration?.accounts?.type === 'console') { - isNewAccount(); - } - - isBlockedCompany(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [companyId]); - - const isNewCompany = (): boolean => { - const oneDay = 1000 * 60 * 60 * 24; - const createdDay = workspace?.group?.stats?.created_at; - const currentDay = Date.now(); - const currentPeriod = Math.round(Math.round(currentDay - createdDay) / oneDay); - - return currentPeriod <= 7 ? true : false; - }; - - const isNewAccount = () => { - if (!workspace?.id) return; - - const isNewUser: boolean = - onboarding !== 'completed' && - workspace?.group?.stats?.total_members <= 1 && - isNewCompany() && - !user?.is_verified; - - if (isNewUser) { - localStorage.setItem(`onboarding_${companyId}`, 'completed'); - return ModalManager.open(<WelcomeOnTwake email={user.email} />, { - position: 'center', - size: { width: '600px' }, - }); - } - }; - - const isBlockedCompany = () => { - if (!companyId) return; - const userGroups: { [key: string]: CompanyType } = Groups.user_groups; - const currentGroup = userGroups[companyId]; - - if (currentGroup?.plan?.billing?.status === 'error') { - return ModalManager.open( - <BlockedCompany />, - { - position: 'center', - size: { width: '600px' }, - }, - false, - ); - } - }; - - return <></>; -}; - -export default CompanyStatusComponent; diff --git a/twake/frontend/src/app/components/OnBoarding/popups/AddMailsInWorkspace.tsx b/twake/frontend/src/app/components/OnBoarding/popups/AddMailsInWorkspace.tsx deleted file mode 100644 index f510b9ca6f..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/popups/AddMailsInWorkspace.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState } from 'react'; -import { Button, Col, Row, Typography } from 'antd'; -import AutoHeight from '../../AutoHeight/AutoHeight'; -import ObjectModal from '../../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import ModalManager from 'app/components/Modal/ModalManager'; -import ConsoleService from 'app/services/Console/ConsoleService'; -import RouterServices from 'services/RouterService'; -import WorkspacesUsers from 'services/workspaces/workspaces_users'; - -type PropsType = {}; - -export default (props: PropsType): JSX.Element => { - const { companyId, workspaceId } = RouterServices.getStateFromRoute(); - const [emails, _setEmails] = useState<string[]>([]); - const [loading, setLoading] = useState<boolean>(false); - - const setEmails = (str: string) => - _setEmails(WorkspacesUsers.fullStringToEmails(str) as string[]); - - const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => setEmails(e.target.value); - - const onClickButton = async () => { - setLoading(true); - - return await ConsoleService.addMailsInWorkspace({ - workspace_id: workspaceId || '', - company_id: companyId || '', - emails, - }).finally(() => { - setLoading(false); - return ModalManager.close(); - }); - }; - - return ( - <ObjectModal - title={Languages.t('components.add_mails_workspace.title_1')} - closable - style={{ height: 600 }} - titleLevel={2} - titleCenter - hideFooterDivider - footerAlign="center" - footer={ - <Row className="x-margin" justify="center"> - <Button onClick={onClickButton} type="primary" size="large" loading={loading}> - {Languages.t('components.add_mails_workspace.button')} - </Button> - </Row> - } - > - <Row - className="x-margin" - style={{ padding: '0 16px', marginTop: 16, marginBottom: 62 }} - justify="center" - > - <Typography.Text - style={{ textAlign: 'center', width: '464px', fontSize: 17, height: '44px' }} - > - {Languages.t('components.add_mails_workspace.title_2')} - </Typography.Text> - </Row> - - <Row className="x-margin" style={{ marginBottom: 12, paddingTop: 32 }} justify="center"> - <Col style={{ width: 400 }}> - <AutoHeight - minHeight="110px" - maxHeight="300px" - onChange={onChange} - placeholder={Languages.t('components.add_mails_workspace.text_area_placeholder')} - /> - </Col> - </Row> - - <Row className="x-margin" style={{ display: 'flex', justifyContent: 'center' }}> - <Typography.Text type="secondary" style={{ width: 380, fontSize: 13, height: 32 }}> - {Languages.t('scenes.app.popup.adduser.adresses_message')} - </Typography.Text> - </Row> - </ObjectModal> - ); -}; diff --git a/twake/frontend/src/app/components/OnBoarding/popups/BlockedAccount.tsx b/twake/frontend/src/app/components/OnBoarding/popups/BlockedAccount.tsx deleted file mode 100644 index 7242d01c66..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/popups/BlockedAccount.tsx +++ /dev/null @@ -1,94 +0,0 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ -import React, { useState } from 'react'; -import { Button, Row, Typography } from 'antd'; -import ObjectModal from '../../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import ConsoleService from 'app/services/Console/ConsoleService'; -import LoginService from 'app/services/login/LoginService'; - -type PropsType = { - email: string; -}; - -export default ({ email }: PropsType): JSX.Element => { - const [loading, setLoading] = useState<boolean>(false); - - const onClickButton = () => { - setLoading(true); - return ConsoleService.verifyMail().finally(() => setLoading(false)); - }; - - return ( - <ObjectModal - title={Languages.t('components.account_verification_status_sentence', [ - Languages.t('components.account_verication_status_blocked'), - ])} - titleColor="var(--white)" - titleCenter - headerStyle={{ backgroundColor: 'var(--red)', color: 'var(--white)', height: 76 }} - hideFooterDivider - footerAlign="center" - footer={ - <> - <Button type="ghost" size="small" onClick={onClickButton} loading={loading}> - {Languages.t('general.re_send')} - </Button> - - <Row justify="center" style={{ marginTop: 16 }}> - <a className="blue_link" onClick={() => LoginService.logout()}> - {Languages.t('scenes.apps.account.account.logout')} - </a> - </Row> - </> - } - > - <Row justify="center" style={{ marginTop: 36 }}> - <Typography.Title - level={3} - style={{ - textAlign: 'center', - margin: 0, - width: 493, - }} - > - {Languages.t('components.blocked_account.trial_period_over')} - </Typography.Title> - </Row> - - <Row justify="center" style={{ marginTop: 24 }}> - <Typography.Text - style={{ - textAlign: 'center', - height: 22, - }} - > - {Languages.t('components.unverified_account.verification_details')} - </Typography.Text> - </Row> - - <Row justify="center" style={{ marginTop: 12 }}> - <Typography.Text - strong - style={{ - textAlign: 'center', - height: '22px', - }} - > - {email} - </Typography.Text> - </Row> - - <Row justify="center" style={{ marginTop: 32, marginBottom: 8 }}> - <Typography.Text - style={{ - textAlign: 'center', - fontSize: 15, - height: '22px', - }} - > - {Languages.t('components.unverified_account.re_send_email')} - </Typography.Text> - </Row> - </ObjectModal> - ); -}; diff --git a/twake/frontend/src/app/components/OnBoarding/popups/BlockedCompany.tsx b/twake/frontend/src/app/components/OnBoarding/popups/BlockedCompany.tsx deleted file mode 100644 index 8c42dc87f3..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/popups/BlockedCompany.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import React from 'react'; -import { Button, Row, Typography, Select } from 'antd'; -import ObjectModal from '../../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import LoginService from 'app/services/login/LoginService'; -import { CompanyType } from 'app/models/Company'; -import { capitalize } from 'lodash'; -import ModalManager from 'app/components/Modal/ModalManager'; -import UserService from 'app/services/user/UserService'; -import Groups from 'services/workspaces/groups.js'; -import { AlertTriangle } from 'react-feather'; -import InitService from 'app/services/InitService'; - -type SwitchCompanyPropsType = { - placeholder?: string; - companiesIds: string[]; -}; - -const { Option } = Select; -const { Text, Title } = Typography; -const SwitchCompany = ({ placeholder, companiesIds }: SwitchCompanyPropsType): JSX.Element => { - const userGroups: { [key: string]: CompanyType } = Groups.user_groups; - const companies = companiesIds - .map(id => userGroups[id]) - .filter(company => company.plan?.billing?.status !== 'error'); - - const onSelect = (companyId: string) => { - Groups.select(userGroups[companyId]); - return ModalManager.close(); - }; - - const onClickBtn = () => LoginService.logout(); - - return ( - (!!companies.length && ( - <Select - placeholder={placeholder || 'Select a company'} - onSelect={onSelect} - style={{ width: 224 }} - > - {companies.map(company => ( - <Option key={company.id} value={company.id}> - {capitalize(company.name)} - </Option> - ))} - </Select> - )) || ( - <Button - type="primary" - style={{ height: 36, width: 163, backgroundColor: 'var(--red)' }} - onClick={onClickBtn} - > - {Languages.t('scenes.app.channelsbar.currentuser.logout')} - </Button> - ) - ); -}; - -export default (): JSX.Element => { - const onClickButton = () => - window.open( - InitService.server_infos?.configuration?.accounts?.console?.company_subscription_url || '', - 'blank', - ); - - return ( - <ObjectModal - title={ - <div style={{ display: 'flex' }}> - <AlertTriangle size={24} /> - <span className="small-left-margin"> - {Languages.t('components.on_boarding.popups.blocked_company.title')} - </span> - </div> - } - titleColor="var(--white)" - titleCenter - headerStyle={{ backgroundColor: 'var(--red)', color: 'var(--white)', height: 76 }} - hideFooterDivider - footerAlign="center" - footerStyle={{ marginBottom: 24 }} - footer={ - <Row justify="space-between" align="middle"> - <div - style={{ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - marginTop: 32, - }} - > - <Button type="ghost" size="large" onClick={onClickButton}> - {Languages.t( - 'components.on_boarding.popups.blocked_company.company_subscription_plan_button', - )} - </Button> - <Text style={{ margin: '8px 0 ' }} strong> - {Languages.t('components.on_boarding.popups.blocked_company.or')} - </Text> - <SwitchCompany - placeholder={Languages.t( - 'components.on_boarding.popups.blocked_company.company_selector', - )} - companiesIds={[...(UserService.getCurrentUser()?.groups_id || [])]} - /> - </div> - </Row> - } - > - <Row justify="center" style={{ marginTop: 36 }}> - <Title - level={3} - style={{ - textAlign: 'center', - margin: 0, - width: 493, - }} - > - {Languages.t('components.on_boarding.popups.blocked_company.description')} - - - - - - {Languages.t('components.on_boarding.popups.blocked_company.learn_more_text')} - - - - ); -}; diff --git a/twake/frontend/src/app/components/OnBoarding/popups/UnverifiedAccount.tsx b/twake/frontend/src/app/components/OnBoarding/popups/UnverifiedAccount.tsx deleted file mode 100644 index 2f7a150cc1..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/popups/UnverifiedAccount.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import React, { useState } from 'react'; -import { Button, Row, Typography } from 'antd'; -import ObjectModal from '../../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import ConsoleService from 'app/services/Console/ConsoleService'; - -type PropsType = { - daysLeft: number; - limit: number; - email: string; -}; - -export default ({ daysLeft, email, limit }: PropsType): JSX.Element => { - const [loading, setLoading] = useState(false); - - const onClickButton = () => { - setLoading(true); - return ConsoleService.verifyMail().finally(() => setLoading(false)); - }; - - return ( - - {Languages.t('general.re_send')} - - } - > - - - {Languages.t('components.unverified_account.typography_text_danger', [daysLeft, limit])} - - - - - - {Languages.t('components.unverified_account.verification_details')} - - - - - - {email} - - - - - - {Languages.t('components.unverified_account.re_send_email')} - - - - ); -}; diff --git a/twake/frontend/src/app/components/OnBoarding/popups/WelcomeOnTwake.tsx b/twake/frontend/src/app/components/OnBoarding/popups/WelcomeOnTwake.tsx deleted file mode 100644 index 11a3ec117e..0000000000 --- a/twake/frontend/src/app/components/OnBoarding/popups/WelcomeOnTwake.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import { Button, Row, Typography } from 'antd'; -import React, { useState } from 'react'; -import Emojione from '../../Emojione/Emojione'; -import ObjectModal from '../../ObjectModal/ObjectModal'; -import Languages from 'services/languages/languages'; -import ModalManager from 'app/components/Modal/ModalManager'; -import AddMailsInWorkspace from './AddMailsInWorkspace'; -import ConsoleService from 'app/services/Console/ConsoleService'; - -type PropsType = { - email: string; -}; - -export default ({ email }: PropsType) => { - const [loading, setLoading] = useState(false); - const openAddMembers = () => - ModalManager.open(, { - position: 'center', - size: { width: '600px' }, - }); - - const onClickButton = () => { - setLoading(true); - return ConsoleService.verifyMail().finally(() => setLoading(false)); - }; - - return ( - - {Languages.t('components.verify_mail.title_1')} - -
- } - closable - style={{ height: 600 }} - titleLevel={2} - titleCenter - footerAlign="center" - hideFooterDivider - footer={ - - } - > - - - {Languages.t('components.verify_mail.title_2')} - - - - - {Languages.t('components.verify_mail.text')} - - - - - - {email} - - - - - - {Languages.t('components.verify_mail.paragraph')} - - - - - - {Languages.t('components.unverified_account.re_send_email')} - - - - - - - - ); -}; diff --git a/twake/frontend/src/app/components/OnlineUserStatus/OnlineUserStatus.tsx b/twake/frontend/src/app/components/OnlineUserStatus/OnlineUserStatus.tsx deleted file mode 100644 index 8c9950c544..0000000000 --- a/twake/frontend/src/app/components/OnlineUserStatus/OnlineUserStatus.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-use-before-define -import React, { Suspense } from 'react'; -import classNames from 'classnames'; - -import { UserType } from 'app/models/User'; -import { useOnlineUser } from 'app/services/OnlineUser/useOnlineUser'; - -import './OnlineUserStatus.scss'; - -type PropsType = { - user: UserType; - size?: 'small' | 'medium' | 'big' -}; - -const WrappedUserStatus = ({ user, size = 'medium' }: PropsType): JSX.Element => { - const userOnlineStatus = useOnlineUser(user.id!); - - return ( -
- ); -}; - -const UserOnlineStatus = (props: PropsType): JSX.Element => { - return ( - }> - - - ); -}; - -export default UserOnlineStatus; diff --git a/twake/frontend/src/app/components/Parameters/Attribute.js b/twake/frontend/src/app/components/Parameters/Attribute.js deleted file mode 100755 index eb96280909..0000000000 --- a/twake/frontend/src/app/components/Parameters/Attribute.js +++ /dev/null @@ -1,87 +0,0 @@ -import React, { Component } from 'react'; - -import Number from 'services/utils/Numbers'; -import AttributesManager from './AttributesManager.js'; -import './Parameters.scss'; -import Languages from 'services/languages/languages'; - -export default class Attribute extends React.Component { - constructor(props) { - super(); - - this.id = Number.unid(); - - this.state = { - parameters_attributes: AttributesManager, - i18n: Languages, - }; - - this.timeout = setTimeout(''); - - Languages.addListener(this); - AttributesManager.addListener(this); - } - componentDidMount() { - if (this.props.autoOpen) { - AttributesManager.toggle(this.id); - } - } - componentWillUnmount() { - clearTimeout(this.timeout); - Languages.removeListener(this); - AttributesManager.removeListener(this); - } - componentDidUpdate() { - var open = this.state.parameters_attributes.open == this.id; - if (open && !this.was_open) { - this.value_node.style.maxHeight = 'none'; - this.value_height = window.getBoundingClientRect(this.value_node).height; - this.value_node.style.maxHeight = '0px'; - clearTimeout(this.timeout); - this.timeout = setTimeout(() => { - this.value_node.style.maxHeight = this.value_height + 'px'; - - this.timeout = setTimeout(() => { - this.value_node.style.maxHeight = 'none'; - this.value_height = window.getBoundingClientRect(this.value_node).height; - }, 200); - }, 50); - - if (this.props.focusOnOpen) { - this.props.focusOnOpen.focus(); - } - } else if (!open && this.was_open) { - clearTimeout(this.timeout); - - this.value_node.style.maxHeight = this.value_height + 'px'; - this.timeout = setTimeout(() => { - this.value_node.style.maxHeight = '0px'; - }, 50); - } - this.was_open = open; - } - render() { - return ( - - ); - } -} diff --git a/twake/frontend/src/app/components/Parameters/AttributesManager.js b/twake/frontend/src/app/components/Parameters/AttributesManager.js deleted file mode 100755 index c1f021831c..0000000000 --- a/twake/frontend/src/app/components/Parameters/AttributesManager.js +++ /dev/null @@ -1,26 +0,0 @@ -import React, { Component } from 'react'; - -import Observable from 'app/services/Depreciated/observable.js'; - -/* - Menus manager service, choose where to generate menu -*/ -class AttributesManager extends Observable { - constructor() { - super(); - this.setObservableName('parameters_attributes'); - - this.open = ''; - } - toggle(id) { - if (this.open == id) { - this.open = ''; - } else { - this.open = id; - } - this.notify(); - } -} - -const service = new AttributesManager(); -export default service; diff --git a/twake/frontend/src/app/components/Picker/Picker.js b/twake/frontend/src/app/components/Picker/Picker.js deleted file mode 100755 index 08748ce1b6..0000000000 --- a/twake/frontend/src/app/components/Picker/Picker.js +++ /dev/null @@ -1,261 +0,0 @@ -import React, { Component } from 'react'; -import AutoComplete from 'components/AutoComplete/AutoComplete'; -import Icon from 'components/Icon/Icon.js'; -import Languages from 'services/languages/languages'; -import './Picker.scss'; - -export default class Picker extends React.Component { - /* - placeholder : string, - search : Array of search function, - renderItem(item) : how to render item - renderItemChoosen(item) : how to add item in input - renderItemSimply(item) : what user will type on input and what we have to replace - onChangeSuggested(list) - onChange(list) : - canCreate - onCreate - disableNavigationKey : - */ - constructor(props) { - super(props); - this.state = { - currentSelected: props.value || [], - inputValue: '', - currentList: [], - selected: [], - }; - this.alreadyBackspace = false; - } - componentWillUnmount() { - document.removeEventListener('click', this.outsideClickListener); - } - componentDidMount() { - if (!this.props.inline) { - this.focus(); - } - - var element = this.container; - this.outsideClickListener = event => { - if (!element.contains(event.target) && document.contains(event.target)) { - this.setState({ focused: false }); - } - }; - this.outsideClickListener = this.outsideClickListener.bind(this); - document.addEventListener('click', this.outsideClickListener); - } - componentWillUpdate(nextProps, nextState) { - if (nextProps.value != this.props.value) { - nextState.currentSelected = nextProps.value; - } - return true; - } - onSelect(item) { - this.alreadyBackspace = true; - if (item && (item.id === undefined || item.id < 0) && item.front_id === undefined) { - this.onCreate(item.textSearched); - return; - } - var newList = this.state.currentSelected; - for (var i = 0; i < newList.length; i++) { - if (newList[i].id == item.id) { - this.setState({ inputValue: '' }); - return false; - } - } - newList.push(item); - this.setState({ currentSelected: newList }); - this.setState({ inputValue: '' }); - if (this.props.onChange) { - this.props.onChange(newList); - } - this.focus(); - } - onRemove(item) { - var newList = this.state.currentSelected; - var index = newList.indexOf(item); - if (index >= 0) { - newList.splice(index, 1); - this.setState({ currentSelected: newList }); - if (this.props.onChange) { - this.props.onChange(newList); - } - } - this.focus(); - } - onBackspace() { - if (this.alreadyBackspace) { - // if already typed on backspace once - var newList = this.state.currentSelected; - newList.splice(newList.length - 1, 1); - this.setState({ currentSelected: newList }); - } else { - this.alreadyBackspace = true; - } - } - onCreate(text) { - if (this.props.onCreate) { - var item = this.props.onCreate(text, item => { - this.onSelect(item); - }); - } - } - focus() { - if (this.autocomplete_node) { - this.autocomplete_node.focus(); - } - } - render() { - var that = this; - var objects = [ -
-
- {this.state.currentSelected.map(item => { - return this.props.renderItemChoosen(item); - })} - {!this.props.readOnly && ( - { - var text = this.state.inputValue; - this.props.search(text, list => { - if (that.props.canCreate && text.length > 0) { - list.push({ id: -1, autocomplete_id: list.length, textSearched: text }); - } - cb(list); - }); - }, - ]} - renderItemChoosen={[ - item => { - if (item.id < 0 && this.props.canCreate) { - return item.textSearched; - } else { - return this.props.renderItemSimply(item); - } - }, - ]} - max={[this.props.max || 10]} - renderItem={[() => {}]} - regexHooked={[/(.*)/]} - placeholder={ - this.state.currentSelected.length - ? '' - : this.props.placeholder || - Languages.t('scenes.apps.drive.left.search', [], 'Search') - } - onChange={evt => { - this.alreadyBackspace = false; - this.setState({ inputValue: evt.target.value }); - }} - onSelect={item => { - this.onSelect(item); - }} - value={this.state.inputValue} - onChangeCurrentList={(list, selected) => { - this.setState({ currentList: list, selected: selected }); - if (this.props.onChangeSuggested) { - this.props.onChangeSuggested(list); - } - }} - hideResult={true} - onBackspace={() => { - this.onBackspace(); - }} - disableNavigationKey={this.props.disableNavigationKey} - showResultsOnInit={true} - onHide={() => this.setState({ focused: false })} - ref={node => { - this.autocomplete_node = node; - }} - /> - )} -
-
, - ]; - - if (!this.props.readOnly) { - if (!this.props.inline) { - objects.push(
{!!this.props.title && this.props.title}
); - } - - var results = []; - - if (this.state.currentList.length > 0) { - results = this.state.currentList.map((item, index) => { - if (item.id < 0) { - return ( -
{ - evt.stopPropagation(); - evt.preventDefault(); - this.onSelect(item); - }} - > -
- - Create {this.props.renderItem(item.textSearched)} -
-
- ); - } else { - return ( -
{ - evt.stopPropagation(); - evt.preventDefault(); - this.onSelect(item); - }} - > -
{this.props.renderItem(item)}
-
- ); - } - }); - } - if (this.props.inline) { - results = ( -
- {results} -
- ); - } - objects = objects.concat(results); - } - - objects = ( -
{ - this.focus(); - this.setState({ focused: true }); - }} - ref={node => (this.container = node)} - className={ - 'picker_container ' + - (this.props.readOnly ? 'readOnly ' : '') + - (this.props.inline ? 'inline ' : '') + - (this.state.focused ? 'focused ' : '') + - this.props.className - } - > - {objects} -
- ); - - return objects; - } -} diff --git a/twake/frontend/src/app/components/PopupComponent/PopupComponent.js b/twake/frontend/src/app/components/PopupComponent/PopupComponent.js deleted file mode 100755 index 9a14d4e6a5..0000000000 --- a/twake/frontend/src/app/components/PopupComponent/PopupComponent.js +++ /dev/null @@ -1,42 +0,0 @@ -import React, { Component } from 'react'; -import './PopupComponent.scss'; -import popupManager from 'services/popupManager/popupManager.js'; -import CloseIcon from '@material-ui/icons/CloseOutlined'; - -export default class PopupComponent extends React.Component { - constructor(props) { - super(props); - this.state = { - popupManager: popupManager, - }; - popupManager.addListener(this); - } - componentWillUnmount() { - popupManager.removeListener(this); - document.removeEventListener('keydown', this.eventClose); - } - componentDidMount() { - document.addEventListener('keydown', this.eventClose); - } - eventClose(evt) { - if (evt.keyCode == 27 && popupManager.canClose()) { - popupManager.close(); - } - } - render() { - return ( -
- {this.state.popupManager.canClose() && ( -
-
this.state.popupManager.close()}> - -
-
- )} -
-
{this.state.popupManager.getComponent()}
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/PopupComponent/PopupComponent.scss b/twake/frontend/src/app/components/PopupComponent/PopupComponent.scss deleted file mode 100755 index cf9241bdd7..0000000000 --- a/twake/frontend/src/app/components/PopupComponent/PopupComponent.scss +++ /dev/null @@ -1,62 +0,0 @@ -.popupComponent { - height: 100%; - width: 100%; - background: white; - position: relative; - .header { - .close { - background: #f2f2f2; - border-radius: 50%; - width: 40px; - height: 40px; - line-height: 40px; - padding: 8px; - box-sizing: border-box; - position: absolute; - right: 10vh; - top: 10vh; - cursor: pointer; - z-index: 10; - line-height: normal; - - &:hover { - background: #eee; - & > * { - opacity: 0.8; - } - } - & > * { - opacity: 0.5; - } - } - } - .componentContainer { - width: 0px; - height: 0px; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - margin: auto; - .component { - width: 100vw; - transform: translateX(-50%) translateY(-50%); - } - } - - @media only screen and (max-width: 600px) { - .header { - .close { - right: auto; - left: 16px; - } - } - .main .content { - margin-left: 0px !important; - } - .main .sideBar { - display: none; - } - } -} diff --git a/twake/frontend/src/app/components/ReminderSelector/ReminderSelector.js b/twake/frontend/src/app/components/ReminderSelector/ReminderSelector.js deleted file mode 100755 index 4e0d7cc4de..0000000000 --- a/twake/frontend/src/app/components/ReminderSelector/ReminderSelector.js +++ /dev/null @@ -1,198 +0,0 @@ -import React, { Component } from 'react'; -import Button from 'components/Buttons/Button.js'; -import Input from 'components/Inputs/Input.js'; -import Icon from 'components/Icon/Icon.js'; -import Select from 'components/Select/Select.js'; -import './ReminderSelector.scss'; -import Languages from 'services/languages/languages'; - -export default class ReminderSelector extends React.Component { - constructor(props) { - super(props); - - this.state = { - reminders: [], - }; - - this.old_value = JSON.stringify(props.reminders || []); - } - - componentDidMount() { - this.updateFromProps(this.props); - } - - shouldComponentUpdate(nextProps, nextState) { - if (this.old_value != JSON.stringify(nextProps.reminders)) { - this.old_value = JSON.stringify(nextProps.reminders); - this.updateFromProps(nextProps); - } - return true; - } - - remove(i) { - delete this.state.reminders[i]; - this.update(); - } - - add() { - this.state.reminders.push({ - mode: 'push', - delay_unit: 'minutes', - delay_value: '30', - }); - this.update(); - } - - update() { - var ret = []; - this.state.reminders.forEach(item => { - if (item.delay_unit == 'minutes' && item.delay_value > 59) { - item.delay_value = 30; - } - if (item.delay_unit == 'hours' && item.delay_value > 23) { - item.delay_value = 1; - } - if (item.delay_unit == 'days' && item.delay_value > 13) { - item.delay_value = 1; - } - if (item.delay_unit == 'weeks' && item.delay_value < 2) { - item.delay_value = 2; - } - - ret.push({ - mode: item.mode, - delay: - parseInt(item.delay_value) * - 60 * - (item.delay_unit == 'hours' ? 60 : 1) * - (item.delay_unit == 'days' ? 60 * 24 : 1) * - (item.delay_unit == 'weeks' ? 60 * 24 * 7 : 1), - }); - }); - - if (this.props.onChange) { - this.props.onChange(ret); - } - - this.setState({}); - } - - updateFromProps(nextProps) { - var props = nextProps || this.props; - - var reminders = []; - - (props.reminders || []).forEach(item => { - var delay_value = parseInt(item.delay / 60); - var delay_unit = 'minutes'; - if (item.delay > 59 * 60) { - delay_value = parseInt(item.delay / (60 * 60)); - delay_unit = 'hours'; - } - if (item.delay > 23 * 60 * 60) { - delay_value = parseInt(item.delay / (60 * 60 * 24)); - delay_unit = 'days'; - } - if (item.delay > 13 * 24 * 60 * 60) { - delay_value = parseInt(item.delay / (60 * 60 * 24 * 7)); - delay_unit = 'weeks'; - } - reminders.push({ - mode: item.mode, - delay_value: delay_value, - delay_unit: delay_unit, - }); - }); - - this.setState({ reminders: reminders }); - } - - render() { - return ( -
- {this.state.reminders.map((reminder, i) => { - return ( -
- { - this.state.reminders[i].delay_value = evt.target.value; - if (!evt.target.value) { - return; - } - this.update(); - }} - style={{ width: 60 }} - /> - - { - this.state.options.application_id = v; - this.setState({}); - }} - /> - -
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/SearchPopup/Parts/QuickResult.js b/twake/frontend/src/app/components/SearchPopup/Parts/QuickResult.js deleted file mode 100755 index 07244b21dc..0000000000 --- a/twake/frontend/src/app/components/SearchPopup/Parts/QuickResult.js +++ /dev/null @@ -1,70 +0,0 @@ -import React, { Component } from 'react'; -import '../SearchPopup.scss'; - -import Emojione from 'components/Emojione/Emojione'; -import Icon from 'components/Icon/Icon.js'; -import User from 'components/User/User.js'; - -export default class QuickResult extends React.Component { - constructor(props) { - super(props); - } - - render() { - return ( -
-
- {(this.props.emoji || this.props.icon || this.props.users) && ( -
- {this.props.emoji && } - {this.props.icon && } - {this.props.users && ( -
- {this.props.users.map(user => { - return ( - - ); - })} - {this.props.users.length > 1 && ( -
{this.props.users.length}
- )} -
- )} -
- )} - -
-
- {(this.props.group || {}).name} - {this.props.group && this.props.workspace && ' • '} - {(this.props.workspace || {}).name} - {this.props.workspaceSuffix} -
-
- {this.props.text} - - {this.props.locked && } - {this.props.public && } - {this.props.muted && } -
-
- -
- -
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/SearchPopup/SearchPopup.js b/twake/frontend/src/app/components/SearchPopup/SearchPopup.js deleted file mode 100755 index cbfab66f51..0000000000 --- a/twake/frontend/src/app/components/SearchPopup/SearchPopup.js +++ /dev/null @@ -1,410 +0,0 @@ -import React from 'react'; -import Search from 'services/search/search.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import UserService from 'services/user/UserService'; -import './SearchPopup.scss'; -import InputIcon from 'components/Inputs/InputIcon.js'; -import QuickResult from './Parts/QuickResult.js'; -import MessagesFilter from './Parts/MessagesFilter.js'; -import Tabs from 'components/Tabs/Tabs.js'; -import PerfectScrollbar from 'react-perfect-scrollbar'; -import PseudoMarkdownCompiler from 'services/Twacode/pseudoMarkdownCompiler'; -import moment from 'moment'; -import Languages from 'services/languages/languages'; -import userAsyncGet from 'services/user/AsyncGet'; - -export default class SearchPopup extends React.Component { - constructor(props) { - super(props); - Search.addListener(this); - this.handleChange = this.handleChange.bind(this); - this.eventKey = this.eventKey.bind(this); - this.state = { - selected: 0, - total: 0, - withFilters: Search.withFilters || false, - hasFilters: Search.hasFilters || false, - filterType: Search.type || false, - }; - } - componentDidMount() { - document.addEventListener('keydown', this.eventKey); - } - componentWillUnmount() { - document.removeEventListener('keydown', this.eventKey); - Search.removeListener(this); - Collections.get('users').removeListener(this); - } - eventKey(evt) { - if (Search.isOpen()) { - if (evt.keyCode === 27) { - //ESC - Search.close(); - } - if (evt.keyCode === 38) { - //UP - this.moved_selector = true; - this.setState({ - selected: (this.state.selected - 1 + this.state.total) % Math.max(1, this.state.total), - }); - } - if (evt.keyCode === 40) { - //DOWN - this.moved_selector = true; - this.setState({ - selected: (this.state.selected + 1 + this.state.total) % Math.max(1, this.state.total), - }); - } - if (evt.keyCode === 13) { - //ENTER - if (this.current_selection) { - Search.select(this.current_selection); - } - } - } - } - componentDidUpdate() { - Search.withFilters = this.state.withFilters; - Search.hasFilters = this.state.hasFilters; - if (this.moved_selector && this.scroller) { - var selected = this.scroller.getElementsByClassName('selected')[0]; - if (selected) { - this.scroller.scrollTop = - selected.offsetTop - selected.offsetHeight / 2 - this.scroller.offsetHeight / 2; - } - } - this.moved_selector = false; - } - handleChange(event) { - if (event) { - Search.setValue(event.target.value); - } - Search.setType(this.state.filterType); - Search.search(); - } - - renderTableData() { - return Search.row.map(data => { - return ( - - {data.id} - - ); - }); - } - - listenUsers() { - if (!this.listen_user_collection) { - Collections.get('users').addListener(this); - this.listen_user_collection = true; - } - } - - render() { - if (!Search.isOpen()) { - this.state.selected = 0; - this.state.total = 0; - Collections.get('users').removeListener(this); - return ''; - } - - var pos_i = 0; - this.state.total = 0; - - var tabs = [ - { - filterType: 'message', - hasFilters: true, - title: Languages.t('components.application.messages', [], 'Messages'), - render: '', - }, - { - filterType: 'file', - hasFilters: true, - title: Languages.t('scenes.apps.drive.navigators.navigator_content.files', [], 'Files'), - render: '', - }, - { - filterType: 'task', - hasFilters: true, - title: Languages.t('components.searchpopup.tasks', [], 'Tasks'), - render: '', - }, - { - filterType: 'event', - hasFilters: true, - title: Languages.t('scenes.app.popup.appsparameters.pages.event_subtitle', [], 'Events'), - render: '', - }, - ]; - - return ( -
-
Search.close()} /> -
-
- (this.input = node)} - onChange={this.handleChange} - onKeyPress={event => { - if (event.key === 'Enter') { - Search.search(); - } - }} - /> - - - -
- { - this.scroller = node; - }} - > - {Search.results.map(item => { - var text = ''; - var emoji = ''; - var icon = ''; - var workspace = undefined; - var group = undefined; - var secret = false; - var ext_members = false; - var users = null; - - try { - var workspace_suffix = ''; - if (item.workspace && item.workspace.name) { - workspace = item.workspace; - group = { id: workspace?.group?.id || workspace.company_id || '' }; - } - - if (item.type === 'channel') { - if (item.channel.application) { - return ''; - } - - if (!item.channel.direct && !item.channel.application) { - emoji = item.channel.icon; - text = item.channel.name; - } - - if (item.channel.direct && !item.channel.application) { - this.listenUsers(); - - users = []; - item.channel.members.forEach(id => { - if (id !== UserService.getCurrentUserId()) { - const user = Collections.get('users').find(id, () => userAsyncGet(id)); - if (user) { - users.push(user); - } - } - }); - - let i_user = 0; - text = ( - users.forEach(user => { - i_user++; - if (user) { - return ( - (i_user > 1 ? ', ' : ' ') + - (item.channel.members > 2 - ? user.first_name || user.username - : UserService.getFullName(user)) - ); - } - }) || [] - ).join(''); - } - - secret = item.channel.private; - ext_members = (item.channel.ext_members || []).length > 0; - } - - if (item.type === 'file') { - if (item.file.detached) { - return ''; - } - icon = item.file.is_directory ? 'folder' : 'file'; - text = item.file.name; - } - - if (item.type === 'task') { - icon = 'check-square'; - text = item.task.title; - - if (item.board) { - workspace_suffix += ' • ' + item.board.title; - } - - if (item.list) { - workspace_suffix += ' • ' + item.list.title; - } - } - - if (item.type === 'event') { - icon = 'calendar-alt'; - text = item.event.title; - - if (item.event.from) { - var dateFrom = moment(item.event.from * 1000).format('L'); - var dateTo = moment(item.event.to * 1000).format('L'); - workspace_suffix += - ' (' + dateFrom + ' ' + moment(item.event.to * 1000).format('LT'); - workspace_suffix += - ' - ' + - moment(item.event.to * 1000).format( - (dateTo !== dateFrom ? 'L' : '') + 'LT', - ); - workspace_suffix += ')'; - } - } - - if (item.type === 'message') { - icon = 'comment'; - text = PseudoMarkdownCompiler.compileToText(item.message.content); - - if (item.channel) { - workspace_suffix += ' • ' + item.channel.name; - } - - workspace_suffix += - ' - ' + moment(item.message.creation_date * 1000).format('L LT'); - } - } catch (e) { - console.log(e); - return ''; - } - - pos_i++; - this.state.total++; - - if (pos_i === this.state.selected + 1) { - this.current_selection = item; - } - - if (this.state.filterType && this.state.filterType !== item.type) { - return ''; - } - - return ( - Search.select(item)} - /> - ); - })} - {!Search.value && ( -
- {Languages.t( - 'components.searchpopup.enter_text', - [], - 'Enter some text to search Twake.', - )} -
- )} - {Search.search_http_loading && Search.value && ( -
- {Languages.t('components.searchpopup.loading', [], 'Loading more results...')} -
- )} - {Search.value && this.state.total == 0 && !Search.search_http_loading && ( -
- {Languages.t('components.user_picker.modal_no_result', [], 'No results found.')} -
- )} - {this.state.total > 0 && Search.scroll_id && !Search.search_http_loading && ( - - )} -
- - {this.state.withFilters && ( - - {this.state.filterType === 'message' && ( - { - Search.setOptions(options); - Search.search(); - }} - /> - )} - - )} -
-
-
-
- ); - } -} diff --git a/twake/frontend/src/app/components/SearchPopup/SearchPopup.scss b/twake/frontend/src/app/components/SearchPopup/SearchPopup.scss deleted file mode 100755 index 2517826733..0000000000 --- a/twake/frontend/src/app/components/SearchPopup/SearchPopup.scss +++ /dev/null @@ -1,282 +0,0 @@ -.searchPopup { - .background { - position: absolute; - z-index: 8; - left: 0; - top: 0; - width: 100%; - height: 100%; - background: #0000002e; - } - - .componentContainer .component .search_body { - display: flex; - height: calc(80vh - 120px); - } - - &.large { - .componentContainer { - margin-top: 10vh; - .component { - max-width: 80vw; - max-height: 80vw; - height: 80vh; - - .filters { - max-width: 400px; - width: 40%; - border-left: 1px solid var(--grey-background); - padding: 16px; - box-sizing: border-box; - } - } - } - } - - .componentContainer { - transition: margin-top 0.2s; - position: absolute; - margin: auto; - top: 0; - bottom: 0; - left: 0; - right: 0; - width: 0px; - height: 0px; - z-index: 9; - transition: top 0.2s, bottom 0.2s, left 0.2s, right 0.2s; - margin-top: 30vh; - - .component { - transform: translateX(-50%); - position: relative; - height: auto; - width: 90vw; - max-width: 500px; - max-height: 50vh; - background: var(--white); - z-index: 1; - box-shadow: 0 2px 32px rgba(0, 0, 0, 0.2); - border-radius: var(--border-radius-base); - padding: 16px; - box-sizing: border-box; - display: flex; - flex-direction: column; - overflow: hidden; - - & > .input_icon { - i { - padding-top: 20px; - } - - .search_input.input { - border-bottom: 1px solid var(--grey-background); - border-radius: 0; - padding-top: 4px; - padding-bottom: 4px; - height: 72px; - } - } - - .results { - flex: 1; - height: auto; - overflow: auto; - } - } - } - - .search_tabs { - display: flex; - border-bottom: 1px solid var(--grey-background); - min-height: 48px; - - .component_tabs { - padding-top: 8px; - flex: 1; - .body { - display: none; - } - .component_tabs_tabs { - border-bottom: 0px; - } - } - .more_filters { - width: 150px; - font-size: 12px; - text-align: right; - padding-right: 16px; - line-height: 46px; - margin-top: 2px; - } - } - - .search_filters { - .section_title:first-child { - margin-top: 0px; - } - } -} - -.searchQuickResult { - border-bottom: 1px solid var(--grey-background); - padding: 8px; - cursor: pointer; - position: relative; - - &.no_workspace_and_group > .selectable { - padding-top: 16px; - padding-bottom: 16px; - & > .icon, - & > .more { - padding-top: 0px; - } - & > .content { - .group_and_workspace { - display: none; - } - .text { - line-height: 24px; - } - } - } - - .selectable { - display: flex; - padding: 8px 16px; - font-weight: 500; - - & > .icon, - & > .more { - min-width: 24px; - padding-top: 16px; - padding-right: 8px; - display: flex; - align-items: center; - - img.emojione { - width: 24px; - } - .icon { - font-size: 18px; - margin-left: 0px; - color: var(--grey-dark); - } - .user_list { - margin-top: -5px; - margin-bottom: -5px; - .user_head { - display: inline-block; - border-color: #fff; - .status { - border-color: #fff; - } - } - .user_head:not(:first-child) { - margin-left: -16px; - } - .group_count { - background: var(--grey-dark); - height: 16px; - color: #ffffff; - margin-right: 0px; - border-radius: var(--border-radius-base); - padding: 2px 4px; - box-sizing: border-box; - line-height: 12px; - font-size: 12px; - display: inline-block; - vertical-align: top; - margin-left: 8px; - margin-top: 6px; - } - } - .right-arrow { - display: none; - position: absolute; - top: 0px; - bottom: 0px; - margin: auto; - height: 24px; - right: 16px; - font-size: 24px; - color: var(--primary); - } - } - - & > .content { - flex: 1; - .group_and_workspace { - color: var(--grey-dark); - font-size: 12px; - margin-bottom: 4px; - min-height: 16px; - } - .text { - font-weight: bold; - font-size: 16px; - span { - margin-right: 8px; - } - } - } - } - - &:hover { - & > .selectable { - background: var(--primary-background); - color: var(--primary); - border-radius: var(--border-radius-base); - } - - & > .selectable > .icon .user_list .user_head { - border-color: var(--grey-background); - .status { - border-color: var(--grey-background); - } - } - - &.selected { - & > .selectable { - background: var(--primary-hover); - - & > .icon .user_list .user_head { - border-color: var(--primary-hover); - .status { - border-color: var(--primary-hover); - } - } - } - } - } - - &.selected > .selectable { - background: var(--primary); - color: var(--white); - border-radius: var(--border-radius-base); - & > .more .right-arrow { - color: var(--white); - } - & > .content .group_and_workspace { - color: var(--primary-background); - } - & > .icon .icon { - color: var(--primary-background); - } - & > .icon .user_list .user_head { - border-color: var(--primary); - .status { - &.grey { - background: var(--primary-background); - } - border-color: var(--primary); - } - } - } - - &:hover > .selectable { - .right-arrow { - display: block; - } - } -} diff --git a/twake/frontend/src/app/components/Select/Select.js b/twake/frontend/src/app/components/Select/Select.js deleted file mode 100755 index 4da68252ac..0000000000 --- a/twake/frontend/src/app/components/Select/Select.js +++ /dev/null @@ -1,71 +0,0 @@ -import React, { Component } from 'react'; - -import MenusManager from 'app/components/Menus/MenusManager.js'; -import Icon from 'components/Icon/Icon.js'; -import './Select.scss'; - -export default class Select extends React.Component { - constructor(props) { - super(); - this.props = props; - } - select(value) { - this.props.onChange(value); - } - openMenu(evt) { - var pos = window.getBoundingClientRect(this.node); - pos.x = pos.x || pos.left; - pos.y = pos.y || pos.top; - MenusManager.openMenu( - this.props.options.map(item => { - return { - type: item.type || 'menu', - text: item.text, - className: item.className, - icon: item.icon, - emoji: item.emoji, - reactElement: item.reactElement, - onClick: () => this.select(item.value), - }; - }), - { x: pos.x + pos.width / 2, y: pos.y + pos.height }, - 'bottom', - ); - } - render() { - var className = this.props.className || ''; - - if (this.props.big) { - className += ' big '; - } - if (this.props.medium) { - className += ' medium '; - } - if (this.props.small) { - className += ' small '; - } - - if ( - className.indexOf('medium') === className.indexOf('small') && - className.indexOf('big') === className.indexOf('small') && - className.indexOf('big') < 0 - ) { - className += ' small'; - } - - var current = - this.props.options.filter(item => { - return item.value == this.props.value; - })[0] || {}; - - return ( -
(this.node = node)} - className={'select ' + className} - onClick={evt => this.openMenu(evt)} - > - {current.icon && } {current.text || current.title || '-'} -
- ); - } -} diff --git a/twake/frontend/src/app/components/StepCounter/StepCounter.js b/twake/frontend/src/app/components/StepCounter/StepCounter.js deleted file mode 100755 index 22d6a5d607..0000000000 --- a/twake/frontend/src/app/components/StepCounter/StepCounter.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Component } from 'react'; - -import './StepCounter.scss'; - -export default class StepCounter extends React.Component { - /* - props : { - current : int - total : int - } - */ - constructor() { - super(); - } - displayStep() { - var ret = []; - for (var i = 0; i < this.props.total; i++) { - ret.push( -
, - ); - } - return ret; - } - render() { - return ( -
- {this.displayStep().map(item => { - return item; - })} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Table/Table.scss b/twake/frontend/src/app/components/Table/Table.scss deleted file mode 100755 index febf641243..0000000000 --- a/twake/frontend/src/app/components/Table/Table.scss +++ /dev/null @@ -1,98 +0,0 @@ -.table { - overflow: hidden; - border-radius: var(--border-radius-base); - margin-bottom: 16px; - border: 1px solid var(--grey-background); - font-weight: 500; - - &.unfocused { - box-shadow: none; - } - - &.loading { - opacity: 0.5; - - .tr .item .line { - pointer-events: none; - border-radius: var(--border-radius-large); - height: 16px; - margin-top: 8px; - width: 200px; - animation-duration: 1s; - animation-fill-mode: forwards; - animation-iteration-count: infinite; - animation-name: placeHolderShimmer; - animation-timing-function: linear; - background-repeat: repeat !important; - background-image: linear-gradient( - to right, - var(--grey-light) 0px, - #f2f2f2 120px, - var(--grey-light) 234px - ) !important; - - & > * { - opacity: 0 !important; - } - } - } - - .headerTable { - background: var(--grey-background); - font-weight: 700; - font-size: 14px; - display: flex; - padding: 8px; - border-bottom: 1px solid var(--grey-background); - } - - .footerTable { - text-align: center; - line-height: 32px; - font-size: 14px; - padding: 5px 10px; - border-top: 1px solid var(--grey-background); - border-bottom: 1px solid var(--grey-background); - } - .contentTable { - .tr { - display: flex; - border-bottom: 1px solid var(--grey-background); - padding: 8px; - font-size: 12px; - - &:hover { - background: var(--grey-background); - } - - &:last-child { - border-bottom: none; - } - - & > div { - position: relative; - min-height: 32px; - - & > .absolute_position { - width: 100%; - position: absolute; - height: 100%; - display: flex; - } - } - } - - .fix_text_padding_medium { - padding: 8px 0; - display: inline-block; - line-height: 18px; - } - - .text-complete-width { - overflow: hidden; - flex: 1; - white-space: nowrap; - text-overflow: ellipsis; - } - } -} diff --git a/twake/frontend/src/app/components/Table/Table.tsx b/twake/frontend/src/app/components/Table/Table.tsx deleted file mode 100755 index 3d28c876db..0000000000 --- a/twake/frontend/src/app/components/Table/Table.tsx +++ /dev/null @@ -1,244 +0,0 @@ -/* eslint-disable jsx-a11y/anchor-is-valid */ -import React, { Component } from 'react'; -import Languages from 'services/languages/languages'; -import Button from 'components/Buttons/Button.js'; -import InputIcon from 'components/Inputs/InputIcon.js'; -import './Table.scss'; - -type Props = { - column?: any; - noHeader: boolean; - onAdd: () => void; - onRequestMore: (refresh: boolean) => Promise; - onSearch: (query: string, maxResults: number, callback: (res: any[]) => void) => Promise; - updatedData: (data: any) => any; - addText?: string; - resultsPerPage?: number; - unFocused: boolean; -}; -type State = { - data: null | any[]; - searchResults: any[]; - loading: boolean; - has_more: boolean; - page: number; - searching: boolean; -}; - -export default class Table extends Component { - searchFieldValue: string = ''; - searchRunning: boolean = false; - searchRunningTimeout: number | null = null; - - constructor(props: Props) { - super(props); - this.state = { - data: null, - searchResults: [], - loading: true, - has_more: true, - page: 0, - searching: false, - }; - Languages.addListener(this); - } - - componentWillUnmount() { - Languages.removeListener(this); - } - - componentDidMount() { - if (this.state.data === null) { - this.requestMore(true); - } - } - - search() { - if (this.searchFieldValue?.length <= 2) { - return false; - } - if (this.searchRunning) { - //@ts-ignore - clearTimeout(this.searchRunningTimeout); - //@ts-ignore - this.searchRunningTimeout = setTimeout(() => { - this.search(); - }, 1000); - return; - } - - this.setState({ - loading: true, - }); - - this.searchRunning = true; - this.props.onSearch(this.searchFieldValue, 10, (data: any[]) => { - this.searchRunning = false; - this.setState({ - loading: false, - searchResults: data, - }); - }); - } - - renderItem(col: any, item: any) { - if (col.render) { - return col.render(item); - } else { - return
{col.dataIndex ? item[col.dataIndex] : ''}
; - } - } - - requestMore(refresh: boolean = false) { - this.setState({ loading: true }); - this.props.onRequestMore(refresh).then(res => { - const hasMore = res.length !== (this.state.data || []).length; - this.setState({ loading: false, data: res, has_more: hasMore }); - }); - } - - setPosition() { - if (this.props.onSearch && !this.props.onAdd) return 'flex-end'; - else return 'space-between'; - } - - nextPage() { - this.setState({ page: this.state.page + 1 }); - if (this.getPageData().length < (this.state.page + 1) * this.getResultsPerPage()) { - this.requestMore(); - } - } - - getPageData() { - const from = this.state.page * this.getResultsPerPage(); - return (this.state.data || []).slice(0, from + this.getResultsPerPage()); - } - - getResultsPerPage(): number { - return this.props.resultsPerPage || 50; - } - - render() { - let page_data = this.state.searching ? this.state.searchResults : this.getPageData(); - page_data = page_data - .map(data => { - data = this.props.updatedData ? this.props.updatedData(data) : data; - if (!data) { - return false; - } - return data; - }) - .filter(i => i); - - return ( -
-
- {this.props.onAdd && ( -
- -
- {!this.props.noHeader && ( -
- {this.props.column.map((col: any) => { - return ( -
- {col.title} -
- ); - })} -
- )} -
- {(page_data || []).length === 0 && !this.state.loading && ( -
-
- {Languages.t('components.user_picker.modal_no_result')} -
-
- )} - {(page_data || []).length === 0 && - !!this.state.loading && - Array.apply(null, Array(this.state.searching ? 1 : this.getResultsPerPage())).map( - () => { - return ( -
-
-
-
-
- ); - }, - )} - {(page_data || []).map((data: any) => { - return ( -
- {this.props.column.map((col: any) => { - return ( -
- {this.renderItem(col, data)} -
- ); - })} -
- ); - })} -
- {!this.state.searching && - !!this.state.has_more && - page_data.length >= this.getResultsPerPage() && ( - - )} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Tabs/Tabs.js b/twake/frontend/src/app/components/Tabs/Tabs.js deleted file mode 100755 index 7a444f3bc3..0000000000 --- a/twake/frontend/src/app/components/Tabs/Tabs.js +++ /dev/null @@ -1,68 +0,0 @@ -import React, { Component } from 'react'; - -import Languages from 'services/languages/languages'; -import PerfectScrollbar from 'react-perfect-scrollbar'; -import './Tabs.scss'; - -export default class Tabs extends Component { - constructor(props) { - super(props); - this.state = { - i18n: Languages, - tab: props.selected, - }; - Languages.addListener(this); - } - componentWillUnmount() { - Languages.removeListener(this); - } - select(i) { - this.setState({ tab: i }); - this.props.onChange && this.props.onChange(i); - } - componentWillUpdate(nextProps, nextState) { - if (nextProps.selected && JSON.stringify(nextProps.selected) != this.oldSelected) { - nextState.tab = nextProps.selected; - this.oldSelected = JSON.stringify(nextProps.selected); - } - } - render() { - var selected = this.state.tab || Object.keys(this.props.tabs || {})[0]; - if (!this.props.tabs[selected]) { - selected = Object.keys(this.props.tabs || {})[0]; - } - - return ( -
- - {Object.keys(this.props.tabs || {}).map(i => { - var item = this.props.tabs[i]; - return ( -
this.select(i)} - > - {typeof item.title == 'function' ? item.title() : item.title} -
- ); - })} -
-
- {typeof this.props.tabs[selected].render == 'function' - ? this.props.tabs[selected].render() - : this.props.tabs[selected].render} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/TagPicker/TagPicker.js b/twake/frontend/src/app/components/TagPicker/TagPicker.js deleted file mode 100755 index 246c52ed0d..0000000000 --- a/twake/frontend/src/app/components/TagPicker/TagPicker.js +++ /dev/null @@ -1,194 +0,0 @@ -import React, { Component } from 'react'; -import Icon from 'components/Icon/Icon.js'; -import Button from 'components/Buttons/Button.js'; -import './TagPicker.scss'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import TagSelector from './TagSelector.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Languages from 'services/languages/languages'; - -export default class TagPicker extends React.Component { - constructor(props) { - super(); - this.props = props; - this.state = { - currentSelected: [], - inputValue: '', - currentList: [], - selected: [], - value: this.props.value || [], - list: props.data || [ - { id: 1, name: Languages.t('scenes.apps.tasks.task_status.todo', [], 'To do') }, - { id: 2, name: Languages.t('scenes.apps.tasks.task_status.current', [], 'Doing') }, - { id: 3, name: Languages.t('scenes.apps.tasks.task_status.done', [], 'Done') }, - ], - }; - } - componentWillUpdate(nextProps, nextState) { - if (JSON.stringify(nextProps.value) != JSON.stringify(this.props.value)) { - this.state.value = nextProps.value; - } - } - componentWillMount() { - if (!this.props.data) { - Collections.get('tags').addListener(this); - Collections.get('tags').addSource( - { - http_base_url: 'globalsearch/tags', - http_options: { - workspace_id: Workspaces.currentWorkspaceId, - }, - websockets: [{ uri: 'tags/' + Workspaces.currentWorkspaceId, options: { type: 'tags' } }], - }, - Workspaces.currentWorkspaceId, - ); - } - } - componentWillUnmount() { - if (!this.props.data) { - Collections.get('tags').removeListener(this); - } - } - addTags(evt) { - var menu = [ - { - type: 'react-element', - reactElement: level => { - return ( - { - if (typeof a == 'string') { - return { name: a, id: a, color: '#888' }; - } else { - return a; - } - }) - : false - } - canCreate={this.props.canCreate} - disabledTags={ - this.state.value.map(item => { - return typeof item == 'string' ? item : item.id; - }) || [] - } - onChange={value => { - value.forEach(tag => { - if ( - this.state.value - .map(item => { - return typeof item == 'string' ? item : item.id; - }) - .indexOf(tag.id || tag.name || tag) < 0 - ) { - this.state.value.push(tag.id || tag.name || tag); - } - }); - if (!this.props.saveButton) this.props.onChange(this.state.value); - this.setState({}); - if (this.props.menu_level !== undefined) { - MenusManager.closeSubMenu(this.props.menu_level); - } else { - MenusManager.closeMenu(); - } - }} - /> - ); - }, - }, - ]; - if (this.props.menu_level !== undefined) { - MenusManager.openSubMenu( - menu, - { x: evt.clientX, y: evt.clientY }, - this.props.menu_level, - 'right', - ); - } else { - MenusManager.openMenu(menu, { x: evt.clientX, y: evt.clientY }, 'right'); - } - } - render() { - var value = this.state.value || []; - - var tag_list = value.map(tag_id => { - var tag = false; - if (this.props.data) { - if (typeof tag_id == 'string') { - tag = { name: tag_id, id: tag_id, color: '#888' }; - } else { - tag = tag_id; - tag.id = tag.id || tag.name; - tag.color = tag.color || '#888'; - } - } else { - tag = Collections.get('tags').find(tag_id); - } - if (!tag) { - return ''; - } - var name = tag.name; - return ( -
- {name}{' '} - {!this.props.readOnly && ( - { - this.state.value.splice(this.state.value.indexOf(tag.id), 1); - if (!this.props.saveButton) this.props.onChange(this.state.value); - this.setState({}); - }} - /> - )} -
- ); - }); - - if (this.props.inline) { - return tag_list; - } - - return ( -
- {!this.props.readOnly && value.length == 0 && ( -
{Languages.t('components.tagpicker.notag', [], 'No tag')}
- )} - - {tag_list} - - {!this.props.readOnly && ( - - )} - - {this.props.saveButton && ( -
-
- )} -
- ); - } -} diff --git a/twake/frontend/src/app/components/TagPicker/TagSelector.js b/twake/frontend/src/app/components/TagPicker/TagSelector.js deleted file mode 100755 index 9094fdbfc8..0000000000 --- a/twake/frontend/src/app/components/TagPicker/TagSelector.js +++ /dev/null @@ -1,219 +0,0 @@ -import React, { Component } from 'react'; -import Picker from 'components/Picker/Picker.js'; -import Button from 'components/Buttons/Button.js'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Icon from 'components/Icon/Icon.js'; -import ColorPicker from 'components/ColorPicker/ColorPicker.js'; -import Strings from 'services/utils/strings.js'; -import InputWithColor from 'components/Inputs/InputWithColor.js'; -import AlertManager from 'services/AlertManager/AlertManager'; -import Languages from 'services/languages/languages'; -import MenusManager from 'app/components/Menus/MenusManager.js'; - -class TagEditor extends React.Component { - constructor(props) { - super(); - this.props = props; - this.state = { - edited_tag_name: '', - edited_tag_color: '', - }; - } - componentWillMount() { - var tag = this.props.tag; - this.state.edited_tag_color = tag.color; - this.state.edited_tag_name = tag.name; - } - saveTag(tag) { - tag.color = this.state.edited_tag_color || tag.color; - tag.name = this.state.edited_tag_name || tag.name; - Collections.get('tags').save(tag, Workspaces.currentWorkspaceId); - MenusManager.closeSubMenu(this.props.level - 1); - } - render() { - var tag = this.props.tag; - return ( -
- { - this.saveTag(tag); - }} - onChange={value => { - this.setState({ edited_tag_color: value[0], edited_tag_name: value[1] }); - }} - /> -
-
-
- ); - } -} - -export default class TagSelector extends React.Component { - constructor(props) { - super(); - this.props = props; - this.state = { - edited_tag_name: '', - edited_tag_color: '', - }; - - this.colors_random_list = ColorPicker.colors.map(a => a).sort(() => Math.random() - 0.5); - this.next_new_color = 0; - } - onUpdate(item) {} - onCreate(text, cb) { - var color = this.colors_random_list[this.next_new_color]; - this.next_new_color = (this.next_new_color + 1) % this.colors_random_list.length; - - var new_tag = Collections.get('tags').edit(); - new_tag.name = text; - new_tag.color = color; - new_tag.workspace_id = Workspaces.currentWorkspaceId; - Collections.get('tags').save(new_tag, Workspaces.currentWorkspaceId, tag => { - cb(new_tag); - }); - - return new_tag; - } - onRemove(item, ev) {} - renderItemChoosen(item) { - return ''; - } - editTag(evt, id) { - var tag = Collections.get('tags').find(id); - if (!tag) { - return; - } - var menu = [ - { type: 'title', text: Languages.t('general.edit') }, - { - type: 'react-element', - reactElement: level => { - return ; - }, - }, - { type: 'separator' }, - { - text: Languages.t('general.remove'), - className: 'error', - icon: 'trash', - onClick: ev => { - var tag = Collections.get('tags').find(id); - if (tag) { - AlertManager.confirm(() => { - MenusManager.closeSubMenu(this.props.level - 1); - Collections.get('tags').remove(tag, Workspaces.currentWorkspaceId); - }); - } - return false; - }, - }, - ]; - MenusManager.openSubMenu(menu, { x: evt.clientX, y: evt.clientY }, this.props.level, 'right'); - } - renderItem(item) { - var add_option = false; - if (typeof item == 'string') { - add_option = true; - item = { name: item, color: this.colors_random_list[this.next_new_color] }; - } - var tag = ( -
= 0 ? 'disabled' : '') - } - style={{ backgroundColor: item.color, margin: '5px 0' }} - > - {item.name} -
- ); - - if (add_option) { - return tag; - } - - return ( -
-
{tag}
- {!add_option && !this.props.data && ( -
{ - ev.stopPropagation(); - ev.preventDefault(); - this.editTag(ev, item.id); - }} - > - -
- )} -
- ); - } - search(text, cb) { - var res = Collections.get('tags').findBy({ workspace_id: Workspaces.currentWorkspaceId }); - if (this.props.data) { - res = this.props.data; - } - - res = res - .filter(function (item) { - if ( - Strings.removeAccents(item.name.toLowerCase().replace(/ +/, '')).indexOf( - Strings.removeAccents(text.toLowerCase().replace(/ +/, '')), - ) !== -1 - ) { - return true; - } - return false; - }) - .sort((a, b) => { - return this.props.disabledTags.indexOf(a.id) >= 0 ? -1 : 1; - }); - cb(res); - } - render() { - return ( - { - this.picker = picker; - }} - title={false} - search={(text, cb) => { - this.search(text, cb); - }} - renderItem={item => { - return this.renderItem(item); - }} - renderItemChoosen={item => { - return this.renderItemChoosen(item); - }} - renderItemSimply={item => { - return item.name; - }} - canCreate={this.props.canCreate !== false} - onCreate={(text, cb) => this.onCreate(text, cb)} - onSelect={item => this.onSelect(item)} - onChange={this.props.onChange} - value={this.props.value} - readOnly={this.props.readOnly} - inline={this.props.inline} - /> - ); - } -} diff --git a/twake/frontend/src/app/components/TaskPicker/TaskPicker.js b/twake/frontend/src/app/components/TaskPicker/TaskPicker.js deleted file mode 100755 index 21db3d15bb..0000000000 --- a/twake/frontend/src/app/components/TaskPicker/TaskPicker.js +++ /dev/null @@ -1,254 +0,0 @@ -import React, { Component } from 'react'; -import Workspaces from 'services/workspaces/workspaces.js'; -import Button from 'components/Buttons/Button.js'; -import Languages from 'services/languages/languages'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Emojione from 'components/Emojione/Emojione'; -import Loader from 'components/Loader/Loader.js'; -import TasksService from 'services/Apps/Tasks/Tasks.js'; -import LeftIcon from '@material-ui/icons/KeyboardArrowLeftOutlined'; - -import './TaskPicker.scss'; - -export default class TaskPicker extends Component { - /* - props : { - mode : "select_board" / "select_task" - } - */ - - constructor(props) { - super(props); - this.tasks_collection_key = 'tasks_picker_' + Workspaces.currentWorkspaceId; - this.collection_key = []; - - this.state = { - taskRepository: Collections.get('task'), - currentBoard: null, - currentList: null, - taskSelected: null, - boardRepository: Collections.get('boards'), - }; - Languages.addListener(this); - Collections.get('boards').addListener(this); - Collections.get('lists').addListener(this); - Collections.get('tasks').addListener(this); - Collections.get('boards').addSource( - { - http_base_url: 'tasks/board', - http_options: { - workspace_id: Workspaces.currentWorkspaceId, - }, - websockets: [ - { uri: 'boards/' + Workspaces.currentWorkspaceId, options: { type: 'board' } }, - ], - }, - this.tasks_collection_key, - ); - } - componentWillUnmount() { - Languages.removeListener(this); - Collections.get('boards').removeSource(this.tasks_collection_key); - Collections.get('lists').removeSource(this.tasks_collection_key); - Collections.get('tasks').removeSource(this.tasks_collection_key); - Collections.get('boards').removeListener(); - Collections.get('lists').removeListener(); - Collections.get('tasks').removeListener(); - } - selectBoard(board) { - if (this.collection_key.indexOf(this.tasks_collection_key + '_' + board.id) < 0) { - this.collection_key.push(this.tasks_collection_key + '_' + board.id); - Collections.get('lists').addSource( - { - http_base_url: 'tasks/list', - http_options: { - board_id: board.id, - }, - websockets: [{ uri: 'board_lists/' + board.id, options: { type: 'list' } }], - }, - this.tasks_collection_key + '_' + board.id, - ); - Collections.get('tasks').addSource( - { - http_base_url: 'tasks/task', - http_options: { - board_id: board.id, - }, - websockets: [{ uri: 'board_tasks/' + board.id, options: { type: 'task' } }], - }, - this.tasks_collection_key + '_' + board.id + '_tasks', - ); - } - this.setState({ currentBoard: board }); - } - selectList(list) { - this.setState({ currentList: list }); - } - selectTask(task) { - this.setState({ taskSelected: task }); - } - submit() { - if (this.props.mode === 'select_task' && this.state.taskSelected) { - if (this.props.onChoose) { - this.props.onChoose(this.state.taskSelected); - } - } - } - renderBoardPicker() { - var boards = Collections.get('boards').findBy({ workspace_id: Workspaces.currentWorkspaceId }); - var loading = - !Collections.get('boards').did_load_first_time[this.tasks_collection_key] && - boards.length === 0; - return ( -
- {loading && ( -
- -
- )} - {!loading && - boards.map(board => { - return ( -
this.selectBoard(board)}> -
- {board.emoji && ( - - )} -
{board.title}
-
-
- ); - })} -
- ); - } - renderListPicker() { - var loading = - !Collections.get('lists').did_load_first_time[ - this.tasks_collection_key + '_' + this.state.currentBoard.id - ]; - var lists = Collections.get('lists').findBy({ board_id: this.state.currentBoard.id }); - return ( -
- {loading && ( -
- -
- )} - {!loading && - lists - .sort( - (a, b) => - TasksService.getElementIndex(a, 'lists_' + a.board_id) - - TasksService.getElementIndex(b, 'lists_' + b.board_id), - ) - .map((item, index) => { - return ( -
{ - this.selectList(item); - }} - > -
-
{item.title}
-
- ); - })} -
- ); - } - renderTaskPicker() { - var loading = - !Collections.get('tasks').did_load_first_time[ - this.tasks_collection_key + '_' + this.state.currentBoard.id + '_tasks' - ]; - var tasks = Collections.get('tasks').findBy({ - board_id: this.state.currentBoard.id, - list_id: this.state.currentList.id, - archived: false, - }); - return ( -
- {loading && ( -
- -
- )} - {!loading && - (tasks || []) - .sort( - (a, b) => - TasksService.getElementIndex(a, 'tasks_' + a.list_id) - - TasksService.getElementIndex(b, 'tasks_' + b.list_id), - ) - .map((item, index) => ( -
{ - this.selectTask(item); - }} - > -
{item.title}
-
- ))} -
- ); - } - render() { - return ( -
- {!this.state.currentBoard && ( -
{Languages.t('scenes.apps.tasks.task')}
- )} - {this.state.currentBoard && !this.state.currentList && ( -
- { - Collections.get('lists').removeListener(); - this.setState({ currentBoard: null }); - }} - /> - {this.state.currentBoard.title} -
- )} - {this.state.currentBoard && this.state.currentList && ( -
- { - Collections.get('tasks').removeListener(); - this.setState({ currentList: null }); - }} - /> - {this.state.currentBoard.title} - {this.state.currentList.title} -
- )} -
- {!this.state.currentBoard && this.renderBoardPicker()} - {this.state.currentBoard && !this.state.currentList && this.renderListPicker()} - {this.state.currentBoard && this.state.currentList && this.renderTaskPicker()} -
-
- {this.props.mode === 'select_task' && - this.state.taskSelected && - this.state.taskSelected.id && ( -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Tooltip/Tooltip.js b/twake/frontend/src/app/components/Tooltip/Tooltip.js deleted file mode 100755 index be0a4c35b3..0000000000 --- a/twake/frontend/src/app/components/Tooltip/Tooltip.js +++ /dev/null @@ -1,113 +0,0 @@ -import React, { Component } from 'react'; - -import './Tooltip.scss'; - -export default class Tooltip extends Component { - /* - props = { - tooltip : text or react element to show - visible : - overable : default : true - position : - } - */ - constructor(props) { - super(props); - this.state = { - top: 'unset', - left: 'unset', - right: 'unset', - bottom: '0px', - }; - } - componentWillUnmount() {} - componentDidUpdate(prevProps, prevState) { - if (this.props.visible === true && prevProps.visible === false) { - this.open(); - } else if (this.props.visible === false && prevProps.visible === true) { - this.close(); - } - } - openWithTimeOut(timeout = 5) { - var that = this; - that.open(); - setTimeout(() => { - that.close(); - }, timeout * 1000); - } - open() { - if (this.props.position === 'left') { - this.setState({ - visible: true, - left: (this.tooltip.clientWidth + 8) * -1 + 'px', - right: 'unset', - }); - } else if (this.props.position === 'right') { - this.setState({ - visible: true, - right: (this.tooltip.clientWidth + 8) * -1 + 'px', - left: 'unset', - }); - } else if (this.props.position === 'bottom') { - this.setState({ - visible: true, - bottom: (this.tooltip.clientHeight + 5) * -1 + 'px', - top: 'unset', - }); - } else { - this.setState({ - visible: true, - top: (this.tooltip.clientHeight + 5) * -1 + 'px', - bottom: 'unset', - }); - } - } - close() { - this.setState({ visible: false, top: 'unset', left: '0px', right: 'unset', bottom: '0px' }); - } - componentDidMount() { - var that = this; - if (this.parent && this.children) { - window.tooltip = this.tooltip; - this.parent.addEventListener('mouseenter', () => { - if (this.props.overable !== false) { - that.open(); - } - }); - this.parent.addEventListener('mouseleave', () => { - if (this.props.overable !== false) { - that.close(); - } - }); - } - } - render() { - return ( -
(this.parent = parent)} - > -
(this.tooltip = obj)} - > - {this.props.tooltip} -
-
(this.children = children)}> - {this.props.children} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Twacode/Compile.tsx b/twake/frontend/src/app/components/Twacode/Compile.tsx deleted file mode 100644 index bc6d9964c3..0000000000 --- a/twake/frontend/src/app/components/Twacode/Compile.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import _ from 'lodash'; -import React from 'react'; -import PseudoMarkdownCompiler from 'services/Twacode/pseudoMarkdownCompiler'; -import { DynamicComponent } from './PseudoMarkdownDictionary'; - -type Props = { - content: any; - isApp: boolean; - eventContainer: any; - textTransform?: any; -}; - -const Compile = (props: Props) => { - let content = props.content; - let isApp = props.isApp; - let eventContainer = props.eventContainer; - let textTransform = props.textTransform; - - if (!content) { - return PseudoMarkdownCompiler.pseudo_markdown['text'].object(''); - } - - if (!textTransform) textTransform = {}; - if (content.formatted || content.prepared) content = content.formatted || content.prepared; - if (typeof content === 'string') content = [content]; - if (content.type || content.start) content = [content]; - - if (!_.isArray(content)) { - content = [content]; - } - - try { - return ( - <> - {content.map((item: any, index: number) => { - if (typeof item === 'string') { - return ( - - {item} - - ); - } else if (Array.isArray(item)) { - return ( - - ); - } else { - let type = PseudoMarkdownCompiler.pseudo_markdown[item.start]; - if (item.type === 'compile' && isApp && typeof item.content === 'string') { - return ( - - ); - } else { - if (item.type) { - type = PseudoMarkdownCompiler.pseudo_markdown_types[item.type]; - } - if (type) { - if (!type.apps_only || isApp) { - //If text transform do it - const old_textTransform = JSON.parse(JSON.stringify(textTransform)); - textTransform = JSON.parse(JSON.stringify(textTransform)); - if (type.textTransform) { - Object.keys(type.textTransform).forEach(key => { - textTransform[key] = type.textTransform[key]; - }); - } - - textTransform = old_textTransform; - - return ( - - - } - data={item} - eventContainer={eventContainer} - textTransform={textTransform} - /> - - ); - } - } - } - } - })} - - ); - } catch (e) {} - - return ( - - An error occured while showing PseudoMarkdownCompiler message. - - ); -}; - -export default Compile; diff --git a/twake/frontend/src/app/components/Twacode/PseudoMarkdownDictionary.tsx b/twake/frontend/src/app/components/Twacode/PseudoMarkdownDictionary.tsx deleted file mode 100644 index 8b371a4784..0000000000 --- a/twake/frontend/src/app/components/Twacode/PseudoMarkdownDictionary.tsx +++ /dev/null @@ -1,374 +0,0 @@ -import React, { ReactNode } from 'react'; - -import Emojione from 'components/Emojione/Emojione'; -import HighlightedCode from 'components/HighlightedCode/HighlightedCode'; -import User from './blocks/User'; -import Chan from './blocks/Chan'; -import File from 'components/Drive/File'; -import InputWithClipBoard from 'components/InputWithClipBoard/InputWithClipBoard.js'; -import UserService from 'services/user/UserService'; -import Button from 'components/Buttons/Button.js'; -import Input from 'components/Inputs/Input.js'; - -export const DynamicComponent = ({ - type, - child, - data, - eventContainer, - textTransform, -}: { - type?: string; - child?: ReactNode; - data?: any; - eventContainer?: any; - textTransform?: any; -}) => { - console.log(type, child); - - if (type === 'text_block_parent') { - return {child}; - } - if (type === 'text') { - return {child}; - } - if (type === 'br') { - return ( - <> -
- {child} - - ); - } - if (type === 'emoji') { - return ; - } - if (type === 'user') { - const split = (data.content || '').split(':'); - const id = data.id || split[1]; - const username = split[0]; - return ( - <> - - - - ); - } - if (type === 'channel') { - const split = (data.content || '').split(':'); - const id = data.id || split[1]; - const name = split[0]; - return ( - <> - - - - ); - } - if (type === 'underline') return
{child}
; - if (type === 'strikethrough') return
{child}
; - if (type === 'bold') return
{child}
; - if (type === 'italic') return
{child}
; - if (type === 'mquote') return
{child}
; - if (type === 'quote') return
{child}
; - if (type === 'nop') { - return <>{child}; - } - - if (type === 'mcode') { - return ; - } - if (type === 'icode') { - return
{(data.content || '').trim()}
; - } - if (type === 'url') { - if (!data.url && data.url !== undefined) { - return {child}; - } - let url = setUrlProtocol(data.url || data.content); - if (data.user_identifier && UserService.getCurrentUser()) { - let separator = '?'; - if (url.indexOf('?') > 0) { - separator = '&'; - } - url += separator + 'twake_user=' + UserService.getCurrentUser().id; - } - return ( - // eslint-disable-next-line react/jsx-no-target-blank - - {child} - - ); - } - if (type === 'markdown_link') { - const linkData = data.content.split(']('); - const url = linkData[1] || ''; - - return ( - - {linkData[0]} - - ); - } - if (type === 'email') { - return ( - - {child} - - ); - } - if (type === 'system') { - return {child}; - } - - if (type === 'file') { - return ( -
- -
- ); - } - if (type === 'image') { - return {data.alt; - } - if (type === 'icon') { - return ; - } - if (type === 'progress_bar') { - return ( -
-
-
- ); - } - if (type === 'attachment') { - return
{child}
; - } - if (type === 'button') { - if (data.inline) { - return ( -
{ - if (data.action_id) { - eventContainer.onAction( - 'interactive_action', - data.action_id, - data.interactive_context || {}, - '', - evt, - ); - } - }} - > - {child} -
- ); - } - return ( - - ); - } - if (type === 'copiable') { - return ; - } - if (type === 'input') { - return ( - { - eventContainer.onAction( - 'interactive_change', - data.passive_id, - data.interactive_context || {}, - evt.target.value, - evt, - ); - }} - /> - ); - } - if (type === 'select') { - return ( - - ); - } - - return <>; -}; - -class PseudoMarkdownDictionary { - render_block: { [key: string]: any } = { - text_block_parent: { - object: (child: any, _object: any, _eventContainer: any, textTransform: any) => ( - - ), - }, - text: { - object: (child: any, _object: any, _eventContainer: any, textTransform: any) => ( - - ), - }, - br: { - object: (child: any) => , - }, - emoji: { - object: (_child: any, data: any) => , - }, - user: { - object: (_child: any, object: any) => , - }, - channel: { - object: (_child: any, object: any) => , - }, - underline: { object: (child: any) => }, - strikethrough: { - object: (child: any) => , - }, - bold: { object: (child: any) => }, - italic: { object: (child: any) => }, - mquote: { object: (child: any) => }, - quote: { object: (child: any) => }, - nop: { object: (child: any) => }, - mcode: { - object: (_child: any, object: any) => , - }, - icode: { - object: (_child: any, object: any) => , - }, - url: { - object: (child: any, object: any) => ( - - ), - }, - markdown_link: { - object: (_child: any, object: any) => , - }, - email: { - object: (child: any, object: any) => ( - - ), - }, - system: { - object: (child: any) => , - }, - file: { - object: (_child: any, object: any) => , - }, - image: { - object: (_child: any, object: any, _eventContainer: any) => ( - - ), - }, - icon: { - object: (_child: any, object: any) => , - }, - progress_bar: { - object: (_child: any, object: any) => , - }, - attachment: { object: (child: any) => }, - button: { - object: (child: any, object: any, eventContainer: any) => ( - - ), - }, - copiable: { - object: (_child: any, object: any) => , - }, - input: { - object: (_child: any, object: any, eventContainer: any) => ( - - ), - }, - select: { - object: (_child: any, object: any, eventContainer: any) => ( - - ), - }, - }; -} - -function setUrlProtocol(url: string) { - let protocol = 'https'; - - if ((url || '').indexOf('http://') >= 0) { - protocol = 'http'; - } - return protocol + '://' + (url || '').replace(/^(https?:\/\/)/, ''); -} - -const service = new PseudoMarkdownDictionary(); -export default service; diff --git a/twake/frontend/src/app/components/Twacode/Twacode.scss b/twake/frontend/src/app/components/Twacode/Twacode.scss deleted file mode 100755 index 9f06eac1c7..0000000000 --- a/twake/frontend/src/app/components/Twacode/Twacode.scss +++ /dev/null @@ -1,340 +0,0 @@ -/* PseudoMarkdownCompiler */ - -.markdown { - & > span, - span > span { - vertical-align: middle; - } - - &.loading_interaction { - .interactive_element { - opacity: 0.5; - pointer-events: none; - } - } - - .emoji-container { - display: inline-block; - vertical-align: middle; - height: 1em; - .emoji-mart-emoji { - vertical-align: top; - } - } - - .inline-files { - display: inline-block; - padding-top: 8px; - - .file { - margin-right: 8px; - } - } - - a { - vertical-align: middle; - overflow: hidden; - max-width: 100%; - display: inline-block; - vertical-align: middle; - overflow-wrap: break-word; - } - .bold { - vertical-align: middle; - display: inline; - font-weight: bold; - } - .italic { - vertical-align: middle; - display: inline; - font-style: italic; - } - .underline { - vertical-align: middle; - display: inline; - text-decoration: underline; - } - .strikethrough { - vertical-align: middle; - display: inline; - text-decoration: line-through; - } - .inline-code, - .multiline-code { - vertical-align: middle; - color: #e6e1dc; - background: #535353; - font-family: monospace; - padding: 0 5px; - white-space: pre-wrap; - max-height: 400px; - overflow: auto; - box-sizing: border-box; - line-break: anywhere; - - pre { - margin-bottom: 0; - } - } - .multiline-code { - color: var(--white); - padding: 5px; - border-radius: var(--border-radius-base); - position: relative; - - pre { - max-height: 360px; - overflow: auto; - } - - .hljs { - border-radius: 6px; - } - - .expander { - cursor: pointer; - position: absolute; - background: #00000088; - background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #535353 50%); - bottom: 0; - padding: 8px; - width: 100%; - } - - .copy { - cursor: pointer; - position: absolute; - bottom: 0px; - right: 8px; - } - } - .inline-code { - border-radius: 3px; - background: #232323; - padding-bottom: 1px; - } - .inline-code { - display: inline; - } - .multiline-code { - display: block; - width: 100%; - margin-top: 5px; - margin-bottom: 10px; - } - .multiline-quote, - .one-line-quote, - blockquote { - display: block; - width: 100%; - border-left: 3px solid var(--grey-dark); - padding-left: 5px; - border-radius: 3px; - box-sizing: border-box; - } - .one-line-quote, - blockquote { - margin-bottom: 5px; - margin-top: 5px; - } - .user_twacode.unknown, - .channel_twacode.unknown { - pointer-events: none; - padding-right: 0px; - color: var(--grey-dark); - background: rgba(0, 0, 0, 0); - } - .user_twacode { - display: inline-flex; - line-height: 18px; - - &.highlighted, - &.with_user.highlighted { - background: #fff892; - font-weight: 500; - box-sizing: border-box; - border-radius: var(--border-radius-base); - } - &.with_user { - font-weight: 500; - box-sizing: border-box; - color: var(--black); - height: 18px; - text-transform: capitalize; - border-radius: var(--border-radius-base); - text-overflow: ellipsis; - white-space: nowrap; - display: inline-block; - padding-right: 5px; - margin-right: -2px; - vertical-align: middle; - background: var(--primary-background); - cursor: pointer; - - &:hover { - color: var(--primary); - } - - .userimage { - width: 16px; - height: 16px; - border-radius: var(--border-radius-base); - display: inline-block; - vertical-align: middle; - background: var(--primary-background); - margin: 1px; - vertical-align: top; - margin-right: 3px; - background-size: cover; - background-position: center; - } - } - } - .channel_twacode { - font-weight: 500; - box-sizing: border-box; - color: var(--black); - height: 18px; - line-height: 18px; - text-transform: capitalize; - border-radius: var(--border-radius-base); - text-overflow: ellipsis; - white-space: nowrap; - display: inline-block; - padding-right: 5px; - margin-right: -2px; - vertical-align: middle; - background: var(--primary-background); - font-weight: 500; - cursor: pointer; - - &:hover { - color: var(--primary); - } - - .emoji-container { - vertical-align: top; - margin-right: 3px; - margin-left: 2px; - margin-top: -2px; - img.emojione { - width: 14px; - margin-left: 4px; - } - } - } - - .user_bloc { - vertical-align: middle; - margin-top: -10px; - transform: translateY(6px); - padding: 4px 5px; - height: 24px; - font-weight: bold; - cursor: pointer; - &:hover { - background: #f2f2f2; - } - } - - .attachment { - padding: 0; - padding-left: 9px; - margin: 5px 0; - position: relative; - &:before { - content: ''; - width: 4px; - border-radius: 2px; - height: 100%; - position: absolute; - left: 0; - top: 0; - background: var(--primary); - } - } - - .progress_bar { - width: 100%; - max-width: 200px; - height: 8px; - border-radius: var(--border-radius-base); - overflow: hidden; - background: rgba(128, 128, 128, 0.1); - margin-top: 5px; - margin-bottom: 5px; - display: inline-block; - vertical-align: middle; - - & > div { - height: 100%; - transition: width 0.5s; - background: var(--primary); - } - } - - .interactive_message_btn, - .interactive_message_input { - margin-right: 8px; - vertical-align: middle; - margin-top: 8px; - max-width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - - &.danger { - background: #ff6c6c; - color: var(--white); - - &:hover { - background: #ee5c5c; - } - } - - &.default { - background: #eee; - color: #000; - - &:hover { - background: #ddd; - } - } - } - - //Inline buttons - .interactive_message_btn.underline { - margin: 0px; - padding: 0px; - display: inline; - cursor: pointer; - vertical-align: middle; - background: transparent !important; - color: #888; - - &:hover { - color: #000; - } - - &.danger { - color: #ff6c6c; - &:hover { - color: #ee5c5c; - } - } - - &.primary { - color: var(--primary); - &:hover { - color: #007ed9; - } - } - } - - .image.twacode { - height: 120px; - margin-top: 8px; - border-radius: var(--border-radius-base); - max-width: 100%; - } -} diff --git a/twake/frontend/src/app/components/Twacode/Twacode.tsx b/twake/frontend/src/app/components/Twacode/Twacode.tsx deleted file mode 100755 index 16ed9dea95..0000000000 --- a/twake/frontend/src/app/components/Twacode/Twacode.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import React, { useState, useEffect } from 'react'; - -import PseudoMarkdownCompiler from 'services/Twacode/pseudoMarkdownCompiler'; -import Compile from './Compile'; -import './Twacode.scss'; - -type Props = { - className?: string; - content: any; - before?: any; - after?: any; - isApp?: boolean; - simple?: boolean; - onPassiveChange?: (type: string, id: string, context: any, value: any) => void; - onAction?: (type: string, id: string, context: any, value: any, evt: any) => void; -}; - -export default React.memo((props: Props) => { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - let container: any = null; - let passives: any = {}; - let loadingInteraction_timeout: any = 0; - let saved_stringified: string = ''; - - const [loadingInteraction, setLoadingInteraction] = useState(false); - - const event_container = { - onAction: (type: string, id: string, context: any, value: any, evt: any) => { - //Button pressed - if (type === 'interactive_action') { - if (props.onAction) { - setLoadingInteraction(true); - clearTimeout(loadingInteraction_timeout); - loadingInteraction_timeout = setTimeout(() => { - saved_stringified = ''; - setLoadingInteraction(false); - }, 5000); - props.onAction(type, id, context, JSON.parse(JSON.stringify(passives)), evt); - } - } - - //Input changed - if (type === 'interactive_change') { - passives[id] = value; - if (props.onPassiveChange) { - props.onPassiveChange(type, id, context, value); - } - } - }, - }; - - useEffect(() => { - var stringified = JSON.stringify([props.content]); - if (stringified !== saved_stringified) { - clearTimeout(loadingInteraction_timeout); - // eslint-disable-next-line react-hooks/exhaustive-deps - saved_stringified = stringified; - setLoadingInteraction(false); - } - return () => { - //Called when element is unmounted - clearTimeout(loadingInteraction_timeout); - }; - }, [props.content]); - - return ( -
(container = node)} - {...props} - className={'markdown ' + (loadingInteraction ? 'loadingInteraction ' : '') + props.className} - > - {!!props.simple && - PseudoMarkdownCompiler.compileToSimpleHTML(props.content, true || props.isApp)} - {!props.simple && ( - - )} -
- ); -}); diff --git a/twake/frontend/src/app/components/Twacode/blocks/Chan.tsx b/twake/frontend/src/app/components/Twacode/blocks/Chan.tsx deleted file mode 100755 index af8a277bc3..0000000000 --- a/twake/frontend/src/app/components/Twacode/blocks/Chan.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import Collections from 'app/services/Depreciated/Collections/Collections'; -import Emojione from 'components/Emojione/Emojione'; -import ChannelsService from 'services/channels/channels'; - -type PropsType = { - // channel id - id: string; - // channel name - name: string; -}; - -export default (props: PropsType): JSX.Element => { - const channel = Collections.get('channels').find(props.id); - - if (!props.id || !channel) { - return #{props.name}; - } - - return ( -
ChannelsService.select(channel)} - > - - {channel.name} -
- ); -}; diff --git a/twake/frontend/src/app/components/Twacode/blocks/User.tsx b/twake/frontend/src/app/components/Twacode/blocks/User.tsx deleted file mode 100644 index 71c4654426..0000000000 --- a/twake/frontend/src/app/components/Twacode/blocks/User.tsx +++ /dev/null @@ -1,88 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import classNames from 'classnames'; -import UserService from 'services/user/UserService'; -import ChannelsService from 'services/channels/channels.js'; -import MenusManager from 'app/components/Menus/MenusManager.js'; -import UserCard from 'app/components/UserCard/UserCard'; -import { UserType } from 'app/models/User'; -import { useUser } from 'app/state/recoil/hooks/useUser'; -import Collections from 'app/services/Depreciated/Collections/Collections'; - -const channelMentions = ['channel', 'everyone', 'all', 'here']; - -type PropsType = { - // User id - id: string; - // user username - username: string; - // should we hide the user image? - hideUserImage: boolean; -}; - -export default (props: PropsType): JSX.Element => { - const collection = Collections.get('users'); - const nodeRef = useRef(null); - const user = useUser(props.id); - - useEffect(() => { - const listener = collection.addListener(useState, [user]); - - return () => { - collection.removeListener(listener); - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [user]); - - const displayUserCard = (user: UserType): void => { - if (!nodeRef.current) { - return; - } - - MenusManager.openMenu( - [ - { - type: 'react-element', - reactElement: () => ( - ChannelsService.openDiscussion([user.id])} /> - ), - }, - ], - (window as any).getBoundingClientRect(nodeRef.current), - null, - { margin: 8 }, - ); - }; - - const highlighted = - props.id === UserService.getCurrentUserId() || channelMentions.includes(props.username); - - if (!props.id) { - return @{props.username}; - } - - if (user) { - return ( -
displayUserCard(user)} - style={{ - paddingLeft: props.hideUserImage ? 5 : 0, - backgroundColor: props.hideUserImage ? 'var(--grey-background)' : '', - }} - > - {!props.hideUserImage && ( -
- )} - {UserService.getFullName(user)} -
- ); - } else { - return @{props.username}; - } -}; diff --git a/twake/frontend/src/app/components/Uploads/UploadManager.js b/twake/frontend/src/app/components/Uploads/UploadManager.js deleted file mode 100755 index 38cd709682..0000000000 --- a/twake/frontend/src/app/components/Uploads/UploadManager.js +++ /dev/null @@ -1,514 +0,0 @@ -import Observable from 'app/services/Depreciated/observable.js'; -import Number from 'services/utils/Numbers'; -import DriveService from 'services/Apps/Drive/Drive.js'; -import Collections from 'app/services/Depreciated/Collections/Collections.js'; -import Resumable from 'services/uploadManager/resumable.js'; -import Globals from 'services/Globals'; -import Api from 'services/Api'; -import JWTStorage from 'app/services/JWTStorage'; - -class UploadManager extends Observable { - constructor() { - super(); - this.setObservableName('upload_manager'); - this.reinit(); - - window.uploadManager = this; - } - - reinit() { - if (this.reinitTimeout) clearTimeout(this.reinitTimeout); - if (this.reinitTimeoutBefore) clearTimeout(this.reinitTimeoutBefore); - this.currentUploadTotalSize = 0; - this.currentUploadTotalNumber = 0; - this.currentUploadedTotalSize = 0; - this.currentUploadedFilesNumber = 0; - this.currentUploadingFilesNumber = 0; - this.currentCancelledFilesNumber = 0; - this.currentWaitingFilesNumber = 0; - this.currentErrorFilesNumber = 0; - this.currentUploadFiles = []; - this.currentUploadStartTime = new Date(); - this.will_close = false; - this.notify(); - } - - reinitAfterDelay() { - if (this.reinitTimeout) clearTimeout(this.reinitTimeout); - if (this.reinitTimeoutBefore) clearTimeout(this.reinitTimeoutBefore); - this.reinitTimeoutBefore = setTimeout(() => { - this.will_close = true; - this.notify(); - this.reinitTimeout = setTimeout(() => { - this.reinit(); - }, 500); - }, 800); - } - - startUpload( - elements, - total_number, - total_size, - drive_parent, - upload_options, - driveCollectionKey, - callback, - ) { - if (this.addElementsRecursive(elements, '')) { - this.uploadRecursive(elements, drive_parent, upload_options, driveCollectionKey, callback); - } else { - this.currentUploadFiles = []; - this.currentUploadTotalNumber = 0; - this.currentUploadTotalSize = 0; - this.currentWaitingFilesNumber = 0; - this.currentUploadStartTime = new Date(); - this.reinit(); - } - } - - addElementsRecursive(elements, path) { - return Object.keys(elements).every(name => { - var element = elements[name]; - if (element.size) { - //File - this.currentUploadTotalSize += element.size; - this.currentUploadTotalNumber++; - this.currentUploadFiles.push({ - unid: Number.unid(), - progress: 0, - cancelled: false, - error: false, - name: name, - path: path, - xhr: null, - file: element, - }); - } else { - //Directory - if (!this.addElementsRecursive(element, path + '/' + name)) { - return false; - } - } - return true; - }); - } - - uploadRecursive(elements, drive_parent, upload_options, driveCollectionKey, callback) { - Object.keys(elements).forEach(name => { - var element = elements[name]; - if (element.size) { - //File - this.uploadFile(element, drive_parent, upload_options, driveCollectionKey, callback); - } else { - //Directory - this.createDirectory(name, drive_parent, upload_options, driveCollectionKey, directory => { - if (callback) callback(directory); - if (directory) { - this.uploadRecursive(element, directory, upload_options, driveCollectionKey); - } - }); - } - }); - } - - createDirectory(name, parent, upload_options, driveCollectionKey, callback) { - if (this.currentUploadingFilesNumber > 4) { - setTimeout(() => { - this.createDirectory(name, parent, upload_options, driveCollectionKey, callback); - }, 500); - return; - } - - this.currentUploadingFilesNumber++; - - DriveService.createDirectory( - upload_options.workspace_id, - name, - parent, - driveCollectionKey, - dir => { - this.currentUploadingFilesNumber--; - if (callback) callback(dir); - }, - ); - } - - abort(elements) { - var that = this; - - if (elements.length === undefined) { - elements = [elements]; - } - - elements.forEach(element => { - if (element.resumable) element.resumable.cancel(); - element.xhr_cancelled = true; - element.cancelled = true; - that.currentCancelledFilesNumber++; - that.currentUploadingFilesNumber--; - - if ( - that.currentUploadedFilesNumber + - that.currentCancelledFilesNumber + - that.currentErrorFilesNumber >= - that.currentUploadTotalNumber - ) { - that.reinitAfterDelay(); - } - }); - - that.notify(); - } - - getFilesTree(event, fcb) { - function newDirectoryApi(input, cb) { - var fd = [], - files = []; - var iterate = function (entries, path, resolve) { - var promises = []; - entries.forEach(function (entry) { - promises.push( - new Promise(function (resolve) { - if ('getFilesAndDirectories' in entry) { - entry.getFilesAndDirectories().then(function (entries) { - iterate(entries, entry.path + '/', resolve); - }); - } else { - if (entry.name) { - var p = (path + entry.name).replace(/^[/\\]/, ''); - fd.push(entry); - files.push(p); - - if (files.length > 1000000) { - return false; - } - } - resolve(); - } - }), - ); - }); - - if (files.length > 1000000) { - return false; - } - - Promise.all(promises).then(resolve); - }; - input.getFilesAndDirectories().then(function (entries) { - new Promise(function (resolve) { - iterate(entries, '/', resolve); - }).then(cb.bind(null, fd, files)); - }); - } - - // old prefixed API implemented in Chrome 11+ as well as array fallback - function arrayApi(input, cb) { - var fd = [], - files = []; - [].slice.call(input.files).forEach(function (file) { - fd.push(file); - files.push(file.webkitRelativePath || file.name); - - if (files.length > 1000000) { - return false; - } - }); - - if (files.length > 1000000) { - return false; - } - - cb(fd, files); - } - - // old drag and drop API implemented in Chrome 11+ - function entriesApi(items, cb) { - var fd = [], - files = [], - rootPromises = []; - - function readEntries(entry, reader, oldEntries, cb) { - var dirReader = reader || entry.createReader(); - dirReader.readEntries(function (entries) { - var newEntries = oldEntries ? oldEntries.concat(entries) : entries; - if (entries.length) { - setTimeout(readEntries.bind(null, entry, dirReader, newEntries, cb), 0); - } else { - cb(newEntries); - } - }); - } - - function readDirectory(entry, path, resolve) { - if (!path) path = entry.name; - readEntries(entry, 0, 0, function (entries) { - var promises = []; - entries.forEach(function (entry) { - promises.push( - new Promise(function (resolve) { - if (entry.isFile) { - entry.file(function (file) { - var p = path + '/' + file.name; - fd.push(file); - files.push(p); - if (files.length > 1000000) { - return false; - } - resolve(); - }, resolve.bind()); - } else readDirectory(entry, path + '/' + entry.name, resolve); - }), - ); - }); - Promise.all(promises).then(resolve.bind()); - }); - } - - [].slice.call(items).forEach(function (entry) { - entry = entry.webkitGetAsEntry(); - if (entry) { - rootPromises.push( - new Promise(function (resolve) { - if (entry.isFile) { - entry.file(function (file) { - fd.push(file); - files.push(file.name); - if (files.length > 1000000) { - return false; - } - resolve(); - }, resolve.bind()); - } else if (entry.isDirectory) { - readDirectory(entry, null, resolve); - } - }), - ); - } - }); - - if (files.length > 1000000) { - return false; - } - - Promise.all(rootPromises).then(cb.bind(null, fd, files)); - } - - var cb = function (event, files, paths) { - var documents_number = paths ? paths.length : 0; - var total_size = 0; - var tree = {}; - (paths || []).forEach(function (path, file_index) { - var dirs = tree; - var real_file = files[file_index]; - - total_size += real_file.size; - - path.split('/').forEach(function (dir, dir_index) { - if (dir.indexOf('.') === 0) { - return; - } - if (dir_index === path.split('/').length - 1) { - dirs[dir] = real_file; - } else { - if (!dirs[dir]) { - dirs[dir] = {}; - } - dirs = dirs[dir]; - } - }); - }); - - fcb(tree, documents_number, total_size); - }; - - if (event.dataTransfer) { - var dt = event.dataTransfer; - if (dt.items && dt.items.length && 'webkitGetAsEntry' in dt.items[0]) { - entriesApi(dt.items, cb.bind(null, event)); - } else if ('getFilesAndDirectories' in dt) { - newDirectoryApi(dt, cb.bind(null, event)); - } else if (dt.files) { - arrayApi(dt, cb.bind(null, event)); - } else cb(); - } else if (event.target) { - var t = event.target; - if (t.files && t.files.length) { - arrayApi(t, cb.bind(null, event)); - } else if ('getFilesAndDirectories' in t) { - newDirectoryApi(t, cb.bind(null, event)); - } else { - cb(event); - } - } else { - fcb(event, 1); - } - } - - uploadFile(element, drive_parent, upload_options, driveCollectionKey, callback, timeout_count) { - this.currentWaitingFilesNumber++; - - if (!timeout_count) { - timeout_count = 0; - } - - if (this.currentUploadingFilesNumber > 4) { - setTimeout(() => { - this.currentWaitingFilesNumber--; - this.uploadFile( - element, - drive_parent, - upload_options, - driveCollectionKey, - callback, - timeout_count + 1, - ); - }, Math.max(30000, 500 * (this.currentWaitingFilesNumber + 1) + Math.random() * 1000)); - return; - } - - this.currentWaitingFilesNumber--; - this.currentUploadingFilesNumber++; - - // eslint-disable-next-line no-unused-vars - var listIndex = 0; - var current_item = 0; - this.currentUploadFiles.forEach((item, i) => { - if (item.file === element) { - listIndex = i; - current_item = item; - } - }); - - var that = this; - - if (current_item.xhr_cancelled === true) { - return; - } - - var extension = element.name.split('.'); - var r_data = { - workspace_id: upload_options.workspace_id, - name: element.name, - extension: extension[extension.length - 1], - }; - - //Use Resumable.js for upload by chunk - var r = new Resumable({ - target: `${Globals.api_root_url}/ajax/driveupload/upload`, - chunkSize: 50000000, - testChunks: false, - simultaneousUploads: 5, - withCredentials: true, - maxChunkRetries: 2, - headers: { - Authorization: JWTStorage.getAutorizationHeader(), - }, - query: { - object: JSON.stringify({ - id: upload_options.new_version ? upload_options.file_id : null, - _once_new_version: upload_options.new_version, - front_id: Number.unid(), - is_directory: false, - name: element.name, - parent_id: drive_parent ? drive_parent.id : null, - workspace_id: upload_options.workspace_id, - detached: upload_options.detached, - }), - }, - generateUniqueIdentifier: (file, event) => { - return 'no_id'; - }, - }); - - current_item.resumable = r; - - current_item.timeout = setTimeout(() => { - this.currentUploadingFilesNumber--; - }, 60000); - - r.on('fileSuccess', function (file, message) { - clearTimeout(current_item.timeout); - - that.currentUploadedFilesNumber++; - that.currentUploadingFilesNumber--; - current_item.progress = 1; - - if ( - that.currentUploadedFilesNumber + - that.currentCancelledFilesNumber + - that.currentErrorFilesNumber >= - that.currentUploadTotalNumber - ) { - that.reinitAfterDelay(); - } - - var resp = JSON.parse(message); - - if (resp.data && resp.data.object) { - Collections.get('drive').updateObject(resp.data.object); - Collections.get('drive').share(resp.data.object); - - if (callback) callback(Collections.get('drive').find(resp.data.object.id)); - - var parent = Collections.get('drive').find(resp.data.object.parent_id); - if (parent) { - parent.size = parseInt(parent.size) + parseInt(resp.data.object.size || 0); - Collections.get('drive').updateObject(parent); - } - } else { - current_item.error = 1; - } - - that.notify(); - }); - r.on('progress', function (file, message) { - current_item.progress = Math.min(r.progress(), 0.99); - that.notify(); - - clearTimeout(current_item.timeout); - current_item.timeout = setTimeout(() => { - this.currentUploadingFilesNumber--; - }, 60000); - }); - r.on('fileError', function (file, message) { - clearTimeout(current_item.timeout); - - that.currentErrorFilesNumber++; - that.currentUploadingFilesNumber--; - current_item.error = true; - - if ( - that.currentUploadedFilesNumber + - that.currentCancelledFilesNumber + - that.currentErrorFilesNumber >= - that.currentUploadTotalNumber - ) { - that.reinitAfterDelay(); - } - - that.notify(); - }); - - r.addFile(element); - - Api.post( - '/ajax/driveupload/preprocess', - { - workspace_id: r_data.workspace_id, - name: r_data.name, - identifier: r_data.identifier, - extension: r_data.extension, - }, - res => { - var identifier = res.identifier; - var file = r.getFromUniqueIdentifier('no_id'); - file.uniqueIdentifier = identifier; - r.upload(); - }, - ); - } -} - -const service = new UploadManager(); -export default service; diff --git a/twake/frontend/src/app/components/Uploads/UploadViewer.js b/twake/frontend/src/app/components/Uploads/UploadViewer.js deleted file mode 100755 index 12e8df5091..0000000000 --- a/twake/frontend/src/app/components/Uploads/UploadViewer.js +++ /dev/null @@ -1,170 +0,0 @@ -import React from 'react'; - -import UploadManager from './UploadManager.js'; -import CloseIcon from '@material-ui/icons/CloseOutlined'; -import './Uploads.scss'; -import moment from 'moment'; -import Languages from 'app/services/languages/languages'; - -export default class UploadViewer extends React.Component { - constructor(props) { - super(); - this.state = { - upload_manager: UploadManager, - }; - UploadManager.addListener(this); - } - componentWillUnmount() { - UploadManager.removeListener(this); - } - render() { - if (this.state.upload_manager.currentUploadTotalNumber <= 0) { - // eslint-disable-next-line react/no-direct-mutation-state - this.state.large = true; - return ''; - } - - var documents = this.state.upload_manager.currentUploadFiles.filter(d => !d.path.substr(1)); - var folders = {}; - var folders_content = {}; - this.state.upload_manager.currentUploadFiles - .filter(d => d.path.substr(1)) - .forEach(d => { - var folder = d.path.substr(1).split('/')[0]; - if (!folders[folder]) { - folders[folder] = { - total: 0, - total_progress: 0, - total_uploaded: 0, - error: true, - cancelled: true, - }; - folders_content[folder] = []; - } - - if (!d.cancelled) { - folders[folder].cancelled = false; - } - - if (!d.error) { - folders[folder].error = false; - } - - if (!d.error && !d.cancelled) { - folders[folder].total++; - folders[folder].total_progress += d.progress; - if (d.progress === 1) { - folders[folder].total_uploaded += 1; - } - - folders_content[folder].push(d); - } - }); - Object.keys(folders).forEach(name => { - documents.push({ - progress: folders[name].total_progress / folders[name].total, - name: name, - cancelled: folders[name].cancelled, - error: folders[name].error, - folder_total: folders[name].total, - folder_total_uploaded: folders[name].total_uploaded, - all_files: folders_content[name], - }); - }); - - var total_finished = - this.state.upload_manager.currentUploadedFilesNumber + - this.state.upload_manager.currentCancelledFilesNumber + - this.state.upload_manager.currentErrorFilesNumber; - var todo = this.state.upload_manager.currentUploadTotalNumber; - - var total_finished_size = this.state.upload_manager.currentUploadFiles - .map(a => { - if (a.error || a.cancelled) { - return (a.file || {}).size || 0; - } - if (a.progress > 0) { - return ((a.file || {}).size || 0) * a.progress; - } - return 0; - }) - .reduce((a, b) => { - return a + b; - }); - var todo_size = this.state.upload_manager.currentUploadFiles - .map(a => { - return (a.file || {}).size || 0; - }) - .reduce((a, b) => { - return a + b; - }); - - var remaining_time = 0; - if (total_finished_size > 0) { - remaining_time = - ((todo_size - total_finished_size) / 1000000) * - ((new Date().getTime() - this.state.upload_manager.currentUploadStartTime) / - (total_finished_size / 1000000)); - } - - return ( -
-
this.setState({ large: !this.state.large })}> - {Languages.t('general.uploading')} {total_finished}/{todo} -
- {remaining_time > 0 && ( -
- Will end {moment(new Date().getTime() + remaining_time).fromNow()} -
- )} -
- {documents - .sort((a, b) => (a.progress === 1) - (b.progress === 1)) - .map(item => { - return ( -
-
-
- {item.name} {item.folder_total !== undefined && '(Folder)'} -
- {item.path && item.path.substr(1) && ( -
{item.path.substr(1)}
- )} - {item.folder_total !== undefined && ( -
- {item.folder_total_uploaded}/{item.folder_total} -
- )} -
{parseInt((item.progress || 0) * 100)}%
-
{ - UploadManager.abort(item.all_files || item); - }} - > - -
-
- ); - })} -
-
- ); - } -} diff --git a/twake/frontend/src/app/components/Uploads/UploadZone.tsx b/twake/frontend/src/app/components/Uploads/UploadZone.tsx deleted file mode 100755 index 19dba96f29..0000000000 --- a/twake/frontend/src/app/components/Uploads/UploadZone.tsx +++ /dev/null @@ -1,329 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-use-before-define -import React from 'react'; - -import UploadManager from './UploadManager'; -import Languages from 'services/languages/languages'; -import { Upload } from 'react-feather'; -import classNames from 'classnames'; -import './Uploads.scss'; -import { Typography } from 'antd'; -import { ToasterService as Toaster } from 'app/services/Toaster'; - -type PropsType = { [key: string]: any }; - -type StateType = { [key: string]: any }; - -type FileInputType = any; - -type FileObjectType = { [key: string]: any }; - -let sharedFileInput: any = null; -export default class UploadZone extends React.Component { - file_input: FileInputType = {}; - stopHoverTimeout: ReturnType | undefined; - node: HTMLDivElement | null = null; - - constructor(props: PropsType) { - super(props); - this.state = { - upload_manager: UploadManager, - }; - UploadManager.addListener(this); - this.paste = this.paste.bind(this); - } - - componentWillUnmount() { - UploadManager.removeListener(this); - } - - componentDidMount() { - this.node && this.watch(this.node, document.body); - - if (!sharedFileInput) { - this.file_input = document.createElement('input'); - this.file_input.type = 'file'; - this.file_input.style.position = 'absolute'; - this.file_input.style.top = '-10000px'; - this.file_input.style.left = '-10000px'; - this.file_input.style.width = '100px'; - this.file_input.multiple = this.props.multiple ? true : false; - - this.setCallback(); - - document.body.appendChild(this.file_input); - - sharedFileInput = this.file_input; - } else { - this.file_input = sharedFileInput; - } - } - - setCallback() { - this.file_input.onchange = (e: any) => { - this.change(e); - }; - } - - open() { - if (this.props.disabled) { - return; - } - - this.setCallback(); - - this.file_input.click(); - } - - /** - * - * @param tree - * @param nb - * @param totalSize - */ - upload(tree: any, nb?: number, totalSize?: number) { - if (this.props.multiple === false) { - nb = 1; - let file: any = null; - Object.keys(tree).every(i => { - const element = tree[i]; - if (element.size) { - file = {}; - file[i] = element; - totalSize = element.size; - return false; - } - return true; - }); - if (!file) { - return; - } - } - UploadManager.startUpload( - tree, - nb, - totalSize, - this.props.parent, - this.props.uploadOptions, - this.props.driveCollectionKey, - this.props.onUploaded, - ); - } - - /** - * - * @param event - */ - change(event: any) { - if (this.props.disabled) return; - - event.preventDefault(); - - console.log(event.target.files, event.target); - - const files = event.target.files || event.dataTransfer.files || []; - if (this.props.onAddFiles && files.length > 0) return this.props.onAddFiles([...files]); - - this.hover(false); - - UploadManager.getFilesTree(event, (tree: any, nb: any, totalSize: any) => { - this.file_input.value = ''; - - if (this.props.filesLimit) { - nb <= this.props.filesLimit - ? this.upload(tree, nb, totalSize) - : Toaster.error( - Languages.t('components.upload.drop_files.toaster.error', [this.props.filesLimit]), - 4, - ); - } else { - this.upload(tree, nb, totalSize); - } - }); - } - - /** - * - * @param currentNode - * @param body - */ - watch(currentNode: HTMLElement, body: HTMLElement) { - /** - * DRAGOVER EVENT - */ - currentNode.addEventListener('dragover', (e: DragEvent) => - currentNode.classList.add('input-drag-focus'), - ); - - body.addEventListener('dragover', (e: DragEvent) => { - body.classList.add('body-drag-focus'); - this.hover(true, e); - - e.preventDefault(); - }); - - /** - * DRAGLEAVE EVENT - */ - currentNode.addEventListener('dragleave', (e: DragEvent) => - currentNode.classList.remove('input-drag-focus'), - ); - - body.addEventListener('dragleave', (e: DragEvent) => { - body.classList.remove('body-drag-focus'); - - if (this.props.onDragLeave) { - this.props.onDragLeave(); - } - - this.hover(false, e); - - e.preventDefault(); - }); - - /** - * DROP EVENT - */ - - currentNode.addEventListener('drop', (e: DragEvent) => { - currentNode.classList.contains('input-drag-focus') && this.change(e); - - e.preventDefault(); - }); - - body.addEventListener('drop', (e: DragEvent) => { - this.hover(false, e); - e.preventDefault(); - }); - - /** - * DRAGENTER EVENT - */ - body.addEventListener('dragenter', (e: DragEvent) => { - if (!this.props.disabled && this.props.onDragEnter) { - this.props.onDragEnter(); - } - - this.hover(true, e); - e.preventDefault(); - - this.setCallback(); - }); - } - - /** - * @param {Blob[]} files - * @returns - */ - uploadFiles(files: any = []) { - if (!this.props.allowPaste || !files.length) { - return; - } - - const filesToUpload: any = {}; - - files.forEach((file: FileObjectType, index: number) => { - const filename = file.name - ? file.name.replace(/\.(png|jpeg|jpg|tiff|gif)$/i, '') - : `file-${index}`; - filesToUpload[filename] = file; - }); - - this.upload(filesToUpload); - } - - /** - * - * @param event - */ - paste(event: any) { - if (this.props.allowPaste) { - const clipboardData: any = event.clipboardData || event.originalEvent.clipboardData; - const items: any = clipboardData.items; - let filename: any = (clipboardData.getData('Text') || 'image').split('\n')[0]; - filename = filename.replace(/\.(png|jpeg|jpg|tiff|gif)$/i, ''); - const types: any = []; - let hasImage: any = false; - let imageBlob: any = false; - let imageType: any = false; - - for (const index in items) { - const item: any = items[index]; - if (item.kind === 'file' && item.type.startsWith('image/')) { - hasImage = true; - imageBlob = item.getAsFile(); - imageType = item.type; - } - types.push(item.type); - } - if (hasImage === true) { - event.preventDefault(); - event.stopPropagation(); - - const blob: any = imageBlob; - filename = filename + '.' + (imageType.split('/')[1] || 'png'); - const file: any = new File([blob], filename, { type: imageType }); - const list: any = {}; - list[filename] = file; - this.upload(list, 1, file.size); - } - } - } - - /** - * - * @param state - * @param event - */ - hover(state: any, event?: any) { - if ( - !this.state.dragover && - (!event || !event.dataTransfer || (event.dataTransfer.types || []).indexOf('Files') < 0) - ) { - return; - } - if (!state) { - this.stopHoverTimeout = setTimeout(() => { - this.setState({ dragover: false }); - }, 200); - return; - } - if (this.stopHoverTimeout) clearTimeout(this.stopHoverTimeout); - if (this.state.dragover !== state) { - this.setState({ dragover: state }); - } - } - - render() { - return ( -
node && (this.node = node)} - style={this.props.style} - className={classNames('upload_drop_zone', this.props.className)} - onClick={() => { - if (!this.props.disableClick) { - this.open(); - } - }} - > - {!this.props.disabled && ( -
-
-
-
- - - {Languages.t('components.upload.drop_files')} - -
-
-
-
- )} - - {this.props.children} -
- ); - } -} diff --git a/twake/frontend/src/app/components/Uploads/Uploads.scss b/twake/frontend/src/app/components/Uploads/Uploads.scss deleted file mode 100755 index 09d76ea456..0000000000 --- a/twake/frontend/src/app/components/Uploads/Uploads.scss +++ /dev/null @@ -1,185 +0,0 @@ -.upload_viewer { - position: absolute; - right: 20px; - bottom: 20px; - width: auto; - height: auto; - box-shadow: var(--box-shadow-base); - border-radius: var(--border-radius-base); - overflow: hidden; - display: flex; - flex-direction: column; - z-index: 100; - - .title { - background: var(--secondary); - color: #eeeeee; - font-size: 14px; - padding: 8px; - margin-bottom: 0px; - cursor: pointer; - } - - .subtitle { - background: var(--primary-background); - color: var(--grey-dark); - font-size: 12px; - padding: 4px 8px; - margin-bottom: 0px; - } - - .uploads { - background: #fff; - flex: 1; - overflow: auto; - max-height: 70vh; - width: 300px; - max-width: 50vw; - - .uploadingFile { - position: relative; - padding: 4px; - border-bottom: 1px solid #eee; - font-size: 13px; - display: flex; - - .name { - flex: 1; - padding: 4px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .progress { - padding: 4px; - } - - .path { - background: var(--secondary); - padding: 4px; - color: #fff; - border-radius: var(--border-radius-base); - max-width: 100px; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - .name, - .path, - .progress { - z-index: 1; - } - - &.done { - border-bottom: 1px solid #a8efa8; - .progress_bar { - width: 100% !important; - background: #b8ffb8; - } - } - - &.stopped { - border-bottom: 1px solid #efa8a8; - .progress_bar { - width: 100% !important; - background: #ffb8b8; - } - } - - .progress_bar { - position: absolute; - height: 100%; - z-index: 0; - background: #e5f3fd; - top: 0; - left: 0; - transition: width 0.2s; - } - - .cancel { - opacity: 0; - pointer-events: none; - background: #f35e5e; - border-radius: 50%; - color: #fff; - margin-left: 10px; - width: 24px; - height: 24px; - padding: 3px; - box-sizing: border-box; - position: absolute; - right: 5px; - top: 3px; - z-index: 2; - cursor: pointer; - &:hover { - background: #e34e4e; - } - } - - &.progress:hover { - .cancel { - opacity: 1; - pointer-events: all; - } - .progress { - opacity: 0; - } - } - } - } -} - -.upload_drop_zone { - height: 100%; - - &.input-drag-focus > .on_drag_over_background.dragover > * { - background: var(--primary-background); - } - - .on_drag_over_background { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - background: var(--white); - z-index: 100; - transition: opacity 0.5s; - pointer-events: none; - opacity: 0; - - &.dragover { - opacity: 1; - } - - .dashed { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - box-sizing: border-box; - - transition: opacity 0.5s; - border: 2px dashed var(--primary-background); - border-radius: var(--border-radius-base); - - .centered { - display: flex; - height: 100%; - align-items: center; - justify-content: center; - - .subtitle { - display: flex; - align-items: center; - margin: 0; - color: var(--primary); - } - } - } - } -} diff --git a/twake/frontend/src/app/components/User/User.js b/twake/frontend/src/app/components/User/User.js deleted file mode 100755 index 4ab45b4e28..0000000000 --- a/twake/frontend/src/app/components/User/User.js +++ /dev/null @@ -1,48 +0,0 @@ -// eslint-disable-next-line no-use-before-define -import React, { Component } from 'react'; - -import UserService from 'services/user/UserService'; -import NotificationParameters from 'services/user/notification_parameters.js'; -import ListenUsers from 'services/user/ListenUsers'; -import UserOnlineStatus from '../OnlineUserStatus/OnlineUserStatus'; - -import './User.scss'; - -export default class User extends Component { - constructor(props) { - super(); - } - componentWillMount() { - ListenUsers.listenUser(this.props.user.id); - } - componentWillUnmount() { - ListenUsers.cancelListenUser(this.props.user.id); - } - render() { - var user = this.props.user; - var notifications_disabled = false; - if (user && NotificationParameters.hasNotificationsDisabled(user.notifications_preferences)) { - notifications_disabled = true; - } - return ( -
- {this.props.withStatus && ( - - )} -
- ); - } -} diff --git a/twake/frontend/src/app/components/UserCard/UserCard.scss b/twake/frontend/src/app/components/UserCard/UserCard.scss deleted file mode 100644 index 61741f8704..0000000000 --- a/twake/frontend/src/app/components/UserCard/UserCard.scss +++ /dev/null @@ -1,50 +0,0 @@ -.user-card { - .content-popup { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-around; - margin-bottom: 8px; - - .avatar { - width: 42px; - margin-right: 8px; - } - - .texts { - flex: 1; - overflow: hidden; - - .title { - margin-bottom: 0px; - font-size: 20px; - font-weight: 500; - } - } - - .text-ellipsis { - white-space: nowrap; - width: 100%; - overflow: hidden; - text-overflow: ellipsis; - } - } - - .mail-container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: flex-start; - - a { - margin-left: 8px; - } - } - - .footer { - text-align: right; - & > div { - display: inline-block; - } - } -} diff --git a/twake/frontend/src/app/components/UserCard/UserCard.tsx b/twake/frontend/src/app/components/UserCard/UserCard.tsx deleted file mode 100644 index 72a7bec785..0000000000 --- a/twake/frontend/src/app/components/UserCard/UserCard.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import Emojione from 'components/Emojione/Emojione'; -import Button from 'components/Buttons/Button'; -import Languages from 'services/languages/languages'; -import User from 'components/User/User'; -import UserService from 'services/user/UserService'; -import { UserType } from 'app/models/User'; -import './UserCard.scss'; - -type PropsType = { - user: UserType; - onClick: (evt: any) => {}; -}; - -export default (props: PropsType): JSX.Element => { - return ( -
-
-
- -
-
-
{UserService.getFullName(props.user)}
-
{`@${(props.user || {}).username || ''}`}
-
-
- -
-
-
- ); -}; diff --git a/twake/frontend/src/app/components/UserListManager/UserListManager.tsx b/twake/frontend/src/app/components/UserListManager/UserListManager.tsx deleted file mode 100755 index aef2ea34d2..0000000000 --- a/twake/frontend/src/app/components/UserListManager/UserListManager.tsx +++ /dev/null @@ -1,267 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { Button, Col, Row, Typography } from 'antd'; -import classNames from 'classnames'; -import TrashIcon from '@material-ui/icons/DeleteOutlined'; - -import Strings from 'app/services/utils/strings'; -import UsersService from 'services/user/UserService'; -import Languages from 'services/languages/languages'; -import Workspaces from 'services/workspaces/workspaces.js'; -import UserOrMail from '../ui/UserOrMail'; -import Icon from '../Icon/Icon'; -import WorkspacesUsers from 'services/workspaces/workspaces_users'; -import AutoCompleteExtended from 'components/AutoCompleteExtended/AutoCompleteExtended'; -import { UserType } from 'app/models/User'; -import UserAPIClient from 'app/services/user/UserAPIClient'; - -import './UserListManager.scss'; - -type PropsType = { - [key: string]: any; -}; - -const UserListManager = (props: PropsType) => { - const [input, setInput] = useState(''); - const [editing, setEditing] = useState(props.autoFocus ? props.autoFocus : false); - const [usersIds, setUsersIds] = useState([...props.users]); - let savedUserProps: string; - - useEffect(() => { - updateStateFromProps(props, true); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const updateStateFromProps = (props: PropsType, force?: boolean) => { - let anti_duplicates: string[] = []; - - const user_ids = props.users - .map((item: any) => item.id || item) - .filter((item: string) => { - const here = anti_duplicates.indexOf(item) < 0; - anti_duplicates.push(item); - return here; - }); - - if (force || JSON.stringify(user_ids) !== savedUserProps) { - setUsersIds([...user_ids]); - savedUserProps = JSON.stringify(user_ids); - } - }; - - const filter = (text: string, callback: (arr: any[]) => any) => { - setInput(text); - if ((text || '').indexOf('@') > 0) { - if ( - props.allowMails && - Strings.verifyMail(text) && - usersIds.indexOf(text.toLocaleLowerCase()) < 0 - ) { - callback([{ email: text.toLocaleLowerCase() }]); - return; - } - callback([]); - return; - } - UserAPIClient.search( - text, - { - scope: props.scope, - companyId: Workspaces.currentGroupId, - workspaceId: Workspaces.currentWorkspaceId, - }, - (res: any) => { - res = res.filter((el: any) => !!el); - callback( - res.filter((item: any) => { - if ( - (props.hideUsersIds || []).indexOf(item.id) >= 0 || - usersIds.indexOf(item.id) >= 0 || - usersIds.indexOf(item) >= 0 - ) { - return false; - } - return true; - }), - ); - }, - ); - }; - - const renderLine = (item: any, added?: boolean): JSX.Element => { - if (!item) { - return <>; - } - - if (item.email && !item.username) { - item = item.email; - } - - const id = item.id || item; - let button: JSX.Element = <>; - - if (added && !props.readOnly) { - if (id !== UsersService.getCurrentUserId() || props.canRemoveMyself) { - button = ( - - { - const filteredList = usersIds.filter((id: any) => - typeof item === 'string' ? item !== id : item.id !== id, - ); - - if (props.onUpdate) props.onUpdate(filteredList); - return setUsersIds(filteredList); - }} - /> - - ); - } - } - - return ( - <> - - {button} - - ); - }; - - const select = (id: string) => { - if (!id) { - return; - } - - if (!usersIds.includes(id)) { - const newArr = usersIds.length > 0 ? [...usersIds, id] : [id]; - setUsersIds(newArr); - setInput(''); - if (props.onUpdate) props.onUpdate(newArr); - } - }; - - return ( -
- {usersIds.length > 0 && ( -
- {usersIds.map((item: string, index: number) => ( -
- - {renderLine(item, true)} - -
- ))} -
- )} - {usersIds.length === 0 && !props.noPlaceholder && ( -
{Languages.t('components.userlistmanager.no_users')}
- )} - {!props.readOnly && ( -
- {!editing && ( - setEditing(true)} - > - {' '} - {props.buttonText || - Languages.t('scenes.apps.parameters.workspace_sections.members.invite_btn')} - - )} - {!!editing && ( - - filter(text, list => { - cb(list.map(u => (u?.user || u))); - }) - } - render={(user: UserType) => ( - }> - - - - - )} - /> - )} - {!!props.showAddMe && usersIds.indexOf(UsersService.getCurrentUser().id) < 0 && ( - select(UsersService.getCurrentUser().id)} - > - {' '} - {Languages.t('components.users_picker.add_me')} - - )} - {!!props.showAddAll && - Object.keys(WorkspacesUsers.getUsersByWorkspace(Workspaces.currentWorkspaceId) || {}) - .length > usersIds.length && - Workspaces.getCurrentWorkspace().stats.total_members < 30 && ( - - )} -
- )} - {(props.onCancel || props.onChange) && ( -
- {props.onCancel && ( -
- )} -
- ); -}; - -export default UserListManager; diff --git a/twake/frontend/src/app/components/UserPicker/UserPicker.js b/twake/frontend/src/app/components/UserPicker/UserPicker.js deleted file mode 100755 index d3a4accb3d..0000000000 --- a/twake/frontend/src/app/components/UserPicker/UserPicker.js +++ /dev/null @@ -1,87 +0,0 @@ -import React, { Component } from 'react'; -import Picker from 'components/Picker/Picker.js'; -import Icon from 'components/Icon/Icon.js'; -import './UserPicker.scss'; -import User from 'components/ui/User.js'; -import UsersService from 'services/user/UserService'; -import Languages from 'services/languages/languages'; - -export default class UserPicker extends React.Component { - /* - hello - */ - constructor(props) { - super(); - this.props = props; - this.state = { - currentSelected: [], - inputValue: '', - currentList: [], - selected: [], - }; - } - componentWillUnmount() {} - onUpdate(item) {} - onRemove(item, ev) {} - renderItem(item, withEditor) { - return ( -
- - - {!this.props.readOnly && withEditor && ( -
{ - this.picker.onRemove(item); - ev.stopPropagation(); - ev.preventDefault(); - }} - > - -
- )} -
- ); - } - search(text, cb) { - UsersService.search(text, { scope: this.props.scope || 'all' }, res => { - cb(res); - }); - } - render() { - return ( - { - this.picker = picker; - }} - title={ - this.props.title || Languages.t('components.drive.modify_uslist', [], 'Modify user list') - } - search={(text, cb) => { - this.search(text, cb); - }} - renderItem={item => { - return this.renderItem(item, false); - }} - renderItemChoosen={item => { - return this.renderItem(item, true); - }} - renderItemSimply={item => { - item = item || {}; - return item.username; - }} - max={10} - onSelect={item => this.onSelect(item)} - onChange={this.props.onChange} - value={this.props.value} - readOnly={this.props.readOnly} - inline={this.props.inline} - /> - ); - } -} diff --git a/twake/frontend/src/app/components/AddUserButton/AddUserButton.scss b/twake/frontend/src/app/components/add-user-button/add-user-button.scss similarity index 100% rename from twake/frontend/src/app/components/AddUserButton/AddUserButton.scss rename to twake/frontend/src/app/components/add-user-button/add-user-button.scss diff --git a/twake/frontend/src/app/components/add-user-button/add-user-button.tsx b/twake/frontend/src/app/components/add-user-button/add-user-button.tsx new file mode 100644 index 0000000000..0380858109 --- /dev/null +++ b/twake/frontend/src/app/components/add-user-button/add-user-button.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import Icon from 'components/icon/icon.js'; +import Languages from 'app/features/global/services/languages-service'; +import './add-user-button.scss'; +import popupManager from 'app/deprecated/popupManager/popupManager.js'; +import AddUserByEmail from 'app/views/client/popup/AddUser/AddUserByEmail'; + +export default () => { + return ( +
{ + return popupManager.open(); + }} + > +
+
+ +
+
+
+ {Languages.t( + 'scenes.app.popup.workspaceparameter.pages.collaboraters_adding_button', + [], + 'Ajouter des collaborateurs', + )} +
+
+ ); +}; diff --git a/twake/frontend/src/app/components/attachment-picker/attachment-picker.js b/twake/frontend/src/app/components/attachment-picker/attachment-picker.js new file mode 100755 index 0000000000..57717a8660 --- /dev/null +++ b/twake/frontend/src/app/components/attachment-picker/attachment-picker.js @@ -0,0 +1,198 @@ +import React, { Component } from 'react'; + +import File from 'components/drive/file'; +import FilePicker from 'components/drive/file-picker/file-picker.js'; +import TaskPicker from 'components/task-picker/task-picker.js'; +import Menu from 'components/menus/menu.js'; +import Icon from 'components/icon/icon.js'; +import Button from 'components/buttons/button.js'; +import UploadZone from 'components/uploads/upload-zone'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Languages from 'app/features/global/services/languages-service'; +import './attachment-picker.scss'; + +export default class AttachmentPicker extends Component { + /* + props : { + readOnly : bool + attachments : [] + onChange + className + } + */ + + getIcon(att) { + if (att.type.toLocaleLowerCase() === 'event') { + return 'calendar-alt'; + } + if (att.type.toLocaleLowerCase() === 'file') { + return 'folder'; + } + if (att.type.toLocaleLowerCase() === 'task') { + return 'check-square'; + } + } + addAttachment(attachment) { + var attachments = this.props.attachments || []; + attachments.push(attachment); + if (this.props.onChange) { + this.props.onChange(attachments); + } + } + removeAttachment(attachment) { + var attachments = this.props.attachments || []; + var index = attachments.indexOf(attachment); + if (index >= 0) { + attachments.splice(index, 1); + if (this.props.onChange) { + this.props.onChange(attachments); + } + } + } + render() { + return ( +
+
+ {(Object.values(this.props.attachments || {}) || []).map(att => { + if (att.type === 'file') { + var additionalMenu = []; + if (!this.props.readOnly) { + additionalMenu = [ + { + type: 'menu', + text: Languages.t( + 'components.attachmentpicker.remove_attach', + [], + 'Remove attachment', + ), + onClick: () => { + this.removeAttachment(att); + }, + }, + ]; + } + return ( +
+ +
+ ); + } + return ( +
+ + {att.name} + {!this.props.readOnly && ( + { + this.removeAttachment(att); + }} + /> + )} +
+ ); + })} +
+ {!this.props.readOnly && ( + { + this.upload_zone.open(); + MenusManager.closeMenu(); + }, + }, + { + type: 'menu', + icon: 'folder', + text: Languages.t( + 'components.attachmentpicker.from_twake', + [], + 'From Twake Documents', + ), + submenu: [ + { + type: 'react-element', + reactElement: ( + { + this.addAttachment({ type: 'file', id: res.id, name: res.name }); + MenusManager.closeMenu(); + }} + initialDirectory={{ id: '' }} + /> + ), + }, + ], + }, + ], + }, + { + type: 'menu', + text: Languages.t('scenes.apps.tasks.task', [], 'Task'), + icon: 'check-square', + submenu: [ + { + type: 'react-element', + reactElement: ( + { + this.addAttachment({ type: 'task', id: res.id, name: res.title }); + MenusManager.closeMenu(); + }} + /> + ), + }, + ], + }, + ]} + > + {' '} + + + )} + + (this.upload_zone = node)} + disableClick + parent={''} + driveCollectionKey={'attachment_' + Workspaces.currentWorkspaceId} + uploadOptions={{ workspace_id: Workspaces.currentWorkspaceId, detached: true }} + onUploaded={res => { + this.addAttachment({ type: 'file', id: res.id, name: res.name }); + }} + multiple={false} + /> +
+ ); + } +} diff --git a/twake/frontend/src/app/components/AttachmentPicker/AttachmentPicker.scss b/twake/frontend/src/app/components/attachment-picker/attachment-picker.scss similarity index 100% rename from twake/frontend/src/app/components/AttachmentPicker/AttachmentPicker.scss rename to twake/frontend/src/app/components/attachment-picker/attachment-picker.scss diff --git a/twake/frontend/src/app/components/auto-complete-extended/auto-complete-extended.tsx b/twake/frontend/src/app/components/auto-complete-extended/auto-complete-extended.tsx new file mode 100644 index 0000000000..569c5c0694 --- /dev/null +++ b/twake/frontend/src/app/components/auto-complete-extended/auto-complete-extended.tsx @@ -0,0 +1,60 @@ +import React, { useState, ReactElement } from 'react'; +import { AutoComplete } from 'antd'; +import { AutoCompleteProps } from 'antd/lib/auto-complete'; + +const { Option } = AutoComplete; + +export default ( + props: { + maxItems?: number; + render?: (item: any) => ReactElement; + onSearch?: (query: string, callback: (res: string[]) => void) => void; + onSelect?: (id: string) => void; + align?: 'top' | 'bottom'; + } & Omit, +) => { + const [list, setList] = useState([]); + const [inputValue, setInputValue] = useState(''); + + const resetInputValue = () => setInputValue(''); + + return ( + { + props.onSearch && + props.onSearch(text, (res: any[]) => { + setList(res); + }); + }} + value={inputValue} + onSelect={(id: string) => { + resetInputValue(); + props.onSelect && props.onSelect(id); + }} + onChange={e => setInputValue(e || '')} + > + {list.slice(0, props.maxItems || 10).map((item: any) => { + return item ? ( + + ) : ( + <> + ); + })} + + ); +}; diff --git a/twake/frontend/src/app/components/AutoComplete/AutoComplete.scss b/twake/frontend/src/app/components/auto-complete/auto-complete.scss similarity index 100% rename from twake/frontend/src/app/components/AutoComplete/AutoComplete.scss rename to twake/frontend/src/app/components/auto-complete/auto-complete.scss diff --git a/twake/frontend/src/app/components/auto-complete/auto-complete.tsx b/twake/frontend/src/app/components/auto-complete/auto-complete.tsx new file mode 100644 index 0000000000..208c8a6b01 --- /dev/null +++ b/twake/frontend/src/app/components/auto-complete/auto-complete.tsx @@ -0,0 +1,399 @@ +import React, { Component } from 'react'; +import AutoHeight from '../auto-height/auto-height'; +import Input from '../inputs/input'; +import './auto-complete.scss'; + +type State = { + currentList: any[]; + selected: number; + resultPosition: string; + selectedUser: object; + focused: any; +}; + +type Props = { + onResize?: any; + autoHeight?: any; + className?: string; + placeholder?: string; + search: ((text: string, cb: (arr: any) => any) => void)[]; + max: number[]; + onSelect?: (obj: object, other: any) => void; + renderItem: ((obj: object) => any)[]; + renderItemChoosen: ((el: any) => any)[]; + regexHooked: any; + onChange?: any; + value?: any; + onChangeCurrentList?: any; + hideResult?: any; + onBackspace?: any; + disableNavigationKey?: any; + showResultsOnInit?: any; + position?: any; + onHide?: any; + onEscape?: any; + keyUp?: any; + onKeyUp?: any; + onKeyDown?: any; + onKeyPress?: any; + onPaste?: any; + onFocusChange?: any; + big?: boolean; + small?: boolean; + autoFocus?: any; +}; + +export default class AutoComplete extends Component { + currentIdFromList = ''; + is_open = false; + input: any; + container: any; + outsideClickListener: any; + currentRegexUsed: any = -1; + + constructor(props: any) { + super(props); + + this.state = { + currentList: [], + selected: -1, + resultPosition: '', + selectedUser: {}, + focused: '', + }; + + this.keyUp = this.keyUp.bind(this); + this.keyDown = this.keyDown.bind(this); + } + keyDown(ev: any) { + const key = ev.which || window.event; + + if ( + this.is_open && + key && + this.currentRegexUsed >= 0 && + this.state.currentList.length > 0 && + (key === 13 || key === 9 || key === 38 || key === 40) + ) { + ev.preventDefault(); + ev.stopPropagation(); + } + if (key === 27 && !this.is_open && this.props.onEscape) { + this.props.onEscape(); + } + if (key === 27 && this.is_open && this.props.onHide) { + this.is_open = false; + this.props.onHide(); + } + } + keyUp(ev: any) { + const key = ev.which; + const allText = this.getValueBeforeCaret(); + if (key === 8 && this.input.value.length === 0 && this.props.onBackspace) { + this.props.onBackspace(); + } + for (let i = 0; i < this.props.regexHooked.length; i++) { + let text = allText.match(this.props.regexHooked[i]); + if (text && allText) { + if (this.currentRegexUsed < 0 || this.currentRegexUsed !== i) { + this.currentRegexUsed = i; + } + text = text[1] || ''; + if ( + key && + !this.props.disableNavigationKey && + (key === 13 || key === 9 || key === 38 || key === 40) && + this.state.currentList.length > 0 + ) { + ev.preventDefault(); + ev.stopPropagation(); + if (key === 13 || key === 9) { + //Select (enter) + this.select((this.state.currentList || {})[this.state.selected]); + } else if (key === 38 || key === 40) { + //Up // down + let nextState = 0; + if ( + (key === 38 && this.state.resultPosition === 'top') || + (key === 40 && this.state.resultPosition === 'bottom') + ) { + nextState = (this.state.selected + 1) % this.state.currentList.length; + } else { + nextState = + (this.state.selected + this.state.currentList.length - 1) % + this.state.currentList.length; + } + this.setState({ + selected: nextState, + }); + this.currentIdFromList = this.getCurrentIdFromList(this.state.currentList, nextState); + } + } else { + this.is_open = true; + this.search(text, i); + } + if (this.props.onChangeCurrentList) { + this.props.onChangeCurrentList(this.state.currentList, this.state.selected); + } + return; + } + } + + this.currentRegexUsed = -1; + this.setState({ currentList: [], resultPosition: '' }); + this.props.keyUp && this.props.keyUp(ev); + } + + getCurrentIdFromList(list: any[], pos: number) { + if (!list[pos]) { + return; + } + const id = list[pos].id || JSON.stringify(list[pos]); + return id; + } + + componentWillUnmount() { + document.removeEventListener('click', this.outsideClickListener); + this.input.removeEventListener('keydown', this.keyDown); + this.input.removeEventListener('keyup', this.keyUp); + } + componentDidMount() { + const element = this.container; + this.outsideClickListener = (event: any) => { + if (!element.contains(event.target) && document.contains(event.target)) { + this.setState({ focused: false }); + } + }; + this.outsideClickListener = this.outsideClickListener.bind(this); + document.addEventListener('click', this.outsideClickListener); + + this.input.addEventListener('keydown', this.keyDown); + this.input.addEventListener('keyup', this.keyUp); + + if (this.props.showResultsOnInit) { + this.currentRegexUsed = 0; + this.search('', 0); + this.props.onChangeCurrentList(this.state.currentList, this.state.selected); + } + } + search(query: any, i: any) { + this.props.search[this.currentRegexUsed](query, results => { + if (!this.is_open) { + return; + } + + const suggestions: any[] = []; + for (let j = 0; j < Math.min(this.props.max[this.currentRegexUsed], results.length); j++) { + results[j].autocomplete_id = j; + suggestions.push(results[j]); + } + + let selection = 0; + + const idsFromSuggestedList = suggestions.map( + (item, index) => (item = this.getCurrentIdFromList(suggestions, index)), + ); + + selection = Math.max(idsFromSuggestedList.indexOf(this.currentIdFromList), 0); + + this.currentRegexUsed = i; + this.setState({ + selected: selection, + currentList: suggestions, + }); + + this.currentIdFromList = this.getCurrentIdFromList(suggestions, selection); + + if (this.props.onChangeCurrentList) { + this.props.onChangeCurrentList(suggestions, this.state.selected); + } + }); + } + getValueBeforeCaret() { + return this.input.value.substr(0, this.input.selectionStart); + } + putTextAtCursor(text: string, alreadyTypedLength: any) { + alreadyTypedLength = alreadyTypedLength || 0; + + const myValue = text; + + if (this.input.selectionStart || this.input.selectionStart === '0') { + const startPos = this.input.selectionStart; + const endPos = this.input.selectionEnd; + this.input.value = + this.input.value.substring(0, startPos - alreadyTypedLength) + + myValue + + this.input.value.substring(endPos, this.input.value.length); + this.input.selectionStart = this.input.selectionStart + myValue.length; + this.input.selectionEnd = this.input.selectionStart + myValue.length; + } else { + this.input.value += myValue; + } + + if (this.props.onChange) this.props.onChange({ target: { value: this.input.value } }); + + this.input.focus(); + this.input.dispatchEvent(new Event('input')); + + this.setState({ + selected: -1, + currentList: [], + }); + } + select(item: any) { + if (!item) { + return; + } + + const m = this.getValueBeforeCaret().match(this.props.regexHooked[this.currentRegexUsed]); + if (m === null) { + return; + } + const alreadyTypedLength = m[0].length; + + this.putTextAtCursor( + this.props.renderItemChoosen[this.currentRegexUsed](item), + alreadyTypedLength, + ); + + if (this.props.onSelect) { + this.props.onSelect(item, this.currentRegexUsed); + } + this.is_open = false; + } + setPositionResult() { + if (this.input && this.state.resultPosition === '' && this.state.currentList.length > 0) { + const size = this.state.currentList.length * 32 + 5; + if ( + //@ts-ignore + document.documentElement.clientHeight - window.getBoundingClientRect(this.input).bottom < + size || + this.props.position === 'top' + ) { + this.setState({ resultPosition: 'top' }); + } else { + this.setState({ resultPosition: 'bottom' }); + } + } + } + focus() { + if (!this.input) { + return; + } + this.input.focus(); + this.setState({ focused: true }); + this.keyUp({}); + } + blur() { + this.input.blur(); + this.setState({ focused: false }); + } + setContent(content: any) { + this.input.value = content; + } + render() { + this.setPositionResult(); + return ( +
{ + this.focus(); + this.setState({ focused: true }); + }} + ref={node => (this.container = node)} + > +
+ {this.props.autoHeight && ( + { + this.input = ref; + }} + onResize={this.props.onResize} + placeholder={this.props.placeholder} + value={this.props.value} + onChange={this.props.onChange} + onKeyUp={this.props.onKeyUp} + onKeyDown={this.props.onKeyDown} + onKeyPress={this.props.onKeyPress} + onPaste={this.props.onPaste} + onFocus={() => { + if (this.props.onFocusChange) { + this.props.onFocusChange(true); + } + }} + onBlur={() => { + if (this.props.onFocusChange) { + this.props.onFocusChange(false); + } + }} + autoFocus={this.props.autoFocus} + /> + )} + {!this.props.autoHeight && ( + { + this.input = ref; + }} + placeholder={this.props.placeholder} + value={this.props.value} + onChange={this.props.onChange} + onKeyUp={this.props.onKeyUp} + onKeyDown={this.props.onKeyDown} + onKeyPress={this.props.onKeyPress} + onPaste={this.props.onPaste} + onFocus={() => { + if (this.props.onFocusChange) { + this.props.onFocusChange(true); + } + }} + onBlur={() => { + if (this.props.onFocusChange) { + this.props.onFocusChange(false); + } + }} + autoFocus={this.props.autoFocus} + /> + )} + {!this.props.hideResult && this.state.currentList.length > 0 ? ( +
+ {this.state.currentList.map((item, index) => { + return ( +
this.select(item)} + > + {item && this.props.renderItem[this.currentRegexUsed](item)} +
+ ); + })} +
+ ) : ( + '' + )} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/auto-height/auto-height.js b/twake/frontend/src/app/components/auto-height/auto-height.js new file mode 100755 index 0000000000..3a4279e3bd --- /dev/null +++ b/twake/frontend/src/app/components/auto-height/auto-height.js @@ -0,0 +1,94 @@ +import React, { Component } from 'react'; +import './auto-height.scss'; + +export default class AutoHeight extends Component { + constructor(props) { + super(); + this.change = this.change.bind(this); + } + componentDidMount() { + this.textarea_offset = + parseInt(this.textarea.style.paddingTop || 0) + + parseInt(this.textarea.style.paddingBottom || 0); + window.addEventListener('resize', this.change); + this.change(); + } + componentWillUnmount() { + window.removeEventListener('resize', this.change); + } + change() { + this.textarea.style.height = '1px'; + var totalHeight = this.textarea.scrollHeight - this.textarea_offset; + this.textarea.style.height = totalHeight + 'px'; + this.container.style.height = totalHeight + 'px'; + if (this.oldHeight !== totalHeight && this.props.onResize) { + this.props.onResize(); + } + this.oldHeight = totalHeight; + } + componentDidUpdate(nextProps) { + this.change(); + } + render() { + var className = this.props.className || ''; + + if (this.props.big) { + className += ' big '; + } + if (this.props.medium) { + className += ' medium '; + } + if (this.props.small) { + className += ' small '; + } + + if ( + className.indexOf('medium') === className.indexOf('small') && + className.indexOf('big') === className.indexOf('small') && + className.indexOf('big') < 0 + ) { + className += ' medium'; + } + + return ( +
(this.container = node)} + className={'input autoheight_container ' + className} + style={{ + display: 'inline-block', + width: '100%', + minHeight: this.props.minHeight ? this.props.minHeight : '', + maxHeight: this.props.maxHeight ? this.props.maxHeight : '', + }} + onMouseEnter={() => { + this.change(); + }} + > + +
+ ); + } +} diff --git a/twake/frontend/src/app/components/AutoHeight/AutoHeight.scss b/twake/frontend/src/app/components/auto-height/auto-height.scss similarity index 100% rename from twake/frontend/src/app/components/AutoHeight/AutoHeight.scss rename to twake/frontend/src/app/components/auto-height/auto-height.scss diff --git a/twake/frontend/src/app/components/Avatar/Avatar.scss b/twake/frontend/src/app/components/avatar/avatar.scss similarity index 100% rename from twake/frontend/src/app/components/Avatar/Avatar.scss rename to twake/frontend/src/app/components/avatar/avatar.scss diff --git a/twake/frontend/src/app/components/avatar/avatar.tsx b/twake/frontend/src/app/components/avatar/avatar.tsx new file mode 100644 index 0000000000..6eee110955 --- /dev/null +++ b/twake/frontend/src/app/components/avatar/avatar.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import { Avatar, AvatarProps, Image } from 'antd'; + +import './avatar.scss'; + +type PropsType = { + url?: string; + size?: number; + shape?: AvatarProps['shape']; + borderRadius?: React.CSSProperties['borderRadius']; + fallback?: string; + onClick?: ((event: React.MouseEvent) => void) | undefined; +}; + +const AvatarComponent = ({ url, shape, size, borderRadius, fallback, onClick }: PropsType) => ( +
+ + } + /> +
+); + +export default AvatarComponent; diff --git a/twake/frontend/src/app/components/banner/banner.scss b/twake/frontend/src/app/components/banner/banner.scss new file mode 100644 index 0000000000..7816c33f17 --- /dev/null +++ b/twake/frontend/src/app/components/banner/banner.scss @@ -0,0 +1,43 @@ + + +.ant-layout-header.banner-container { + padding: 0 16px; + + &.primary { + background-color: var(--primary); + color: var(--white); + } + + &.secondary { + background-color: var(--secondary); + color: var(--white); + border-bottom: 1px solid var(--black); + } + + &.default { + background-color: var(--primary-background); + color: var(--black); + } + + &.warning { + background-color: var(--warning); + color: var(--white); + } + &.important { + background-color: var(--red); + color: var(--white); + } + + &.ghost { + background-color: transparent; + color: var(--black); + } + + .banner-col-icon { + display: flex; + align-items: center; + .icon { + cursor: pointer; + } + } +} diff --git a/twake/frontend/src/app/components/banner/banner.tsx b/twake/frontend/src/app/components/banner/banner.tsx new file mode 100644 index 0000000000..c87adf7eb8 --- /dev/null +++ b/twake/frontend/src/app/components/banner/banner.tsx @@ -0,0 +1,48 @@ +import React, { FC } from 'react'; +import { Col, Layout, Row } from 'antd'; +import './banner.scss'; +import { X } from 'react-feather'; +import { CSSProperties } from '@material-ui/styles'; + +type PropsType = { + closable?: boolean; + content?: string | JSX.Element; + onClose?: () => any; + height?: string | number; + type: 'primary' | 'secondary' | 'default' | 'warning' | 'important' | 'ghost'; + style?: CSSProperties; + contentColumnStyle?: CSSProperties; + className?: string; +}; + +const Banner: FC = ({ + closable, + content, + onClose, + height, + type, + children, + style, + contentColumnStyle, + className, +}) => { + const headerStyle = { + height: height ? height : 68, + lineHeight: height ? `${height}px` : '68px', + ...style, + }; + + return ( + + + + {content || children || ''} + + {closable && } + + + + ); +}; + +export default Banner; diff --git a/twake/frontend/src/app/components/buttons/button-with-timeout.js b/twake/frontend/src/app/components/buttons/button-with-timeout.js new file mode 100755 index 0000000000..e06cccd763 --- /dev/null +++ b/twake/frontend/src/app/components/buttons/button-with-timeout.js @@ -0,0 +1,72 @@ +import React from 'react'; + +import Loader from 'components/loader/loader.js'; +import Button from './button.js'; +import './buttons.scss'; + +export default class ButtonWithTimeout extends React.Component { + /* + props = { + loading : boolean + value : text in button + loadingTimeout : time before show loading + disabled + onClick + style + className + } + */ + constructor(props) { + super(); + this.state = { + showLoader: false, + }; + this.timeout = ''; + } + componentWillUnmount() { + clearTimeout(this.timeout); + } + componentDidUpdate(prevProps, prevState) { + var that = this; + if (prevProps.loading && !this.props.loading) { + if (this.state.showLoader) { + this.setState({ showLoader: false }); + } + clearTimeout(this.timeout); + } else if (!prevProps.loading && this.props.loading) { + this.timeout = setTimeout(function () { + that.setState({ showLoader: true }); + }, this.props.loadingTimeout || 2000); + } + } + render() { + return ( +
+ +
+ {this.state.showLoader && } +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/buttons/button.js b/twake/frontend/src/app/components/buttons/button.js new file mode 100755 index 0000000000..d790996717 --- /dev/null +++ b/twake/frontend/src/app/components/buttons/button.js @@ -0,0 +1,39 @@ +import React from 'react'; +import './buttons.scss'; + +export default class Button extends React.Component { + render() { + var className = this.props.className || ''; + + if (this.props.big) { + className += ' big '; + } + if (this.props.medium) { + className += ' medium '; + } + if (this.props.small) { + className += ' small '; + } + + if ( + className.indexOf('medium') === className.indexOf('small') && + className.indexOf('big') === className.indexOf('small') && + className.indexOf('big') < 0 + ) { + className += ' small'; + } + return ( + + ); + } +} diff --git a/twake/frontend/src/app/components/buttons/buttons.scss b/twake/frontend/src/app/components/buttons/buttons.scss new file mode 100755 index 0000000000..7013a393d6 --- /dev/null +++ b/twake/frontend/src/app/components/buttons/buttons.scss @@ -0,0 +1,185 @@ +.buttonWithTimeout_container { + position: relative; + pointer-events: none; + + & > * { + pointer-events: all; + } + + .buttonWithTimeout { + padding: 0px 35px; + transition: padding 0.5s; + } + .loaderContainer { + color: #fff; + top: 0px; + right: 8px; + position: absolute; + display: inline-block; + transition: opacity 0.5s; + opacity: 0; + height: 100%; + align-items: center; + display: inline-flex; + .loader { + width: 30px; + height: 30px; + } + } + + &.is_loading { + .buttonWithTimeout { + padding-right: 45px; + padding-left: 25px; + } + .loaderContainer { + opacity: 1; + } + } +} + +.button, .button.no-tw { + background-color: var(--primary); + color: var(--white); + font-weight: 500; + border: 0px; + border-radius: var(--border-radius-base); + display: inline-block; + vertical-align: middle; + cursor: pointer; + + &:hover { + background-color: var(--primary-hover); + } + &:active { + background-color: var(--primary); + } + &:focus { + outline: none; + } + &.disabled, + &:disabled { + background-color: var(--primary-background); + pointer-events: none; + } + + &.small { + height: 32px; + line-height: 32px; + padding: 0px 8px; + font-size: 14px; + } + + &.medium { + height: 40px; + line-height: 40px; + padding: 0px 12px; + font-size: 16px; + } + + &.big { + height: 64px; + font-size: 18px; + line-height: 64px; + padding: 0px 24px; + } + + &.secondary { + background: #807f8a; + color: var(--white); + + &:hover { + background: #706f79; + } + &:active { + background: #696871; + } + &.disabled, + &:disabled { + background: #bcbcc2; + } + } + + &.danger { + background: #ff1020; + color: var(--white); + + &:hover { + background: #f00010; + } + &:active { + background: #d80000; + } + &.disabled, + &:disabled { + background: #ffa0a0; + } + } + + &.secondary-light { + background-color: var(--grey-light); + color: var(--black); + + &:hover, + &:active { + opacity: 0.9; + } + &.disabled, + &:disabled { + background-color: var(--grey-background); + color: var(--grey-dark); + } + } + + &.primary-text { + background: transparent; + color: var(--primary); + font-size: 12px; + padding: 0 2px; + .m-icon-small { + font-size: 14px !important; + &:before { + margin: 0px; + } + } + &.disabled, + &:disabled { + color: var(--primary-background); + } + &:hover { + color: var(--primary-hover); + // background-color: var(--primary-background); + } + &:active { + // background-color: var(--primary-background); + } + } + + &.secondary-text { + background: transparent; + color: var(--grey-dark); + font-size: 12px; + padding: 0 2px; + .m-icon-small { + font-size: 14px !important; + &:before { + margin: 0px; + } + } + &.disabled, + &:disabled { + color: var(--primary-background); + } + &:hover { + color: var(--black); + //background-color: var(--grey-background); + } + &:active { + color: var(--black); + } + } + + .m-icon-small { + height: 100%; + } +} diff --git a/twake/frontend/src/app/components/calendar/calendar-selector/calendar-selector.js b/twake/frontend/src/app/components/calendar/calendar-selector/calendar-selector.js new file mode 100755 index 0000000000..ddcaa260c0 --- /dev/null +++ b/twake/frontend/src/app/components/calendar/calendar-selector/calendar-selector.js @@ -0,0 +1,167 @@ +import React from 'react'; +import './calendar-selector.scss'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Select from 'components/select/select.js'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import WorkspacesService from 'app/deprecated/workspaces/workspaces.js'; +import Languages from 'app/features/global/services/languages-service'; + +export default class CalendarSelector extends React.Component { + constructor(props) { + super(); + this.props = props; + + this.state = { + selected: [], + }; + } + + delete(item) { + var list = this.props.value.map(item => item.calendar_id); + const index = list.indexOf(item.id); + if (index >= 0) { + list.splice(index, 1); + this.change(list); + } + MenusManager.closeMenu(); + } + + openMenu(evt, item) { + if (this.props.readonly) { + return; + } + MenusManager.openMenu( + [ + { + className: 'error', + icon: 'trash', + text: Languages.t('components.calendar.calendarselector.remove', [], 'Retirer'), + onClick: () => { + this.delete(item); + }, + }, + ], + { x: evt.clientX, y: evt.clientY, width: 150 }, + 'bottom', + ); + } + + change(list) { + if (this.props.onChange) + this.props.onChange( + list + .map(id => { + var cal = Collections.get('calendars').find(id); + if (!cal) { + return undefined; + } + return { + calendar_id: cal.id, + workspace_id: cal.workspace_id, + }; + }) + .filter(item => item), + ); + } + + render() { + var nb_known_workspaces = 0; + var external_workspace = null; + + return ( +
+
+ {this.props.value.map(ws_cal_id => { + if (ws_cal_id.workspace_id) { + if (WorkspacesService.user_workspaces[ws_cal_id.workspace_id]) { + external_workspace = Collections.get('workspaces').find(ws_cal_id.workspace_id); + } + } + + var item = Collections.get('calendars').find(ws_cal_id.calendar_id); + if (!item || item.workspace_id !== WorkspacesService.currentWorkspaceId) { + return ''; + } + nb_known_workspaces++; + return ( +
(this.node = node)} + onClick={evt => this.openMenu(evt, item)} + className={'calendar_item ' + (this.props.readonly ? '' : 'removable')} + > +
+ {'' + item.title} +
+ ); + })} + + {(!this.props.value || this.props.value.length === 0) && ( +
+ {Languages.t( + 'components.calendar.calendarselector.no_workspace_calendar', + [], + "Aucun calendrier d'espace de travail.", + )} +
+ )} +
+ + {!this.props.readonly && ( +
+ this.input.blur()} + onEnter={() => this.input.blur()} + onBlur={() => this.blur()} + onFocus={() => this.focus()} + placeholder={'No date'} + value={this.state.time_ts ? this.state.time_string : ''} + style={{ maxWidth: 108 }} + onChange={evt => this.process(evt.target.value)} + refInput={node => (this.input = node)} + big={this.props.big} + medium={this.props.medium} + small={this.props.small} + /> + {this.props.withReset && ( +
{ + this.setState({ time_ts: false }); + this.props.onChangeBlur(this.state.time_ts); + this.setState({}); + }} + > + +
+ )} + +
+ ); + } +} diff --git a/twake/frontend/src/app/components/Calendar/DatePicker.scss b/twake/frontend/src/app/components/calendar/date-picker.scss similarity index 100% rename from twake/frontend/src/app/components/Calendar/DatePicker.scss rename to twake/frontend/src/app/components/calendar/date-picker.scss diff --git a/twake/frontend/src/app/components/calendar/day-picker/day-picker.js b/twake/frontend/src/app/components/calendar/day-picker/day-picker.js new file mode 100755 index 0000000000..5d92f9711f --- /dev/null +++ b/twake/frontend/src/app/components/calendar/day-picker/day-picker.js @@ -0,0 +1,165 @@ +import React, { Component } from 'react'; +import Icon from 'components/icon/icon.js'; +import moment from 'moment'; +import './day-picker.scss'; + +export default class DayPicker extends React.Component { + /* + this.props :{ + onChange(day) + value : Array of selected days + } + */ + constructor(props) { + super(props); + this.state = { + days: [], + currentDate: moment(), + }; + this.openSelected = false; + window.moment = moment; + } + componentWillUnmount() {} + componentDidMount() { + this.setState(this.updateDay()); + } + componentWillUpdate(nextProps, nextState) { + if (moment(nextProps.value).valueOf() != this.oldProp) { + var obj = this.updateDay(nextProps.value); + nextState.days = obj.days; + nextState.currentDate = obj.currentDate; + } + this.oldProp = moment(nextProps.value).valueOf(); + } + updateDay(date) { + var searchedDate = date || moment(); + var days = []; + var first_day_of_month = moment(searchedDate).startOf('month').startOf('week'); + for (var i = 0; i < 35; i++) { + days.push(moment(moment(first_day_of_month).add(i, 'days'))); + } + return { + days: days, + currentDate: searchedDate, + }; + } + isSelected(day) { + if (this.props.value) { + if ( + Array.isArray(this.props.value) && + this.props.value.length == 2 && + this.props.value[0] && + this.props.value[1] + ) { + return day.isBetween(this.props.value[0], this.props.value[1], 'day', '[]'); + } else if ( + Array.isArray(this.props.value) && + this.props.value.length >= 1 && + this.props.value[0] + ) { + return day.isSame(this.props.value[0], 'day'); + } else if (!Array.isArray(this.props.value) && this.props.value) { + return day.isSame(this.props.value, 'day'); + } + } + return false; + } + isLast(day) { + if (this.props.value) { + if ( + Array.isArray(this.props.value) && + this.props.value.length == 2 && + this.props.value[0] && + this.props.value[1] + ) { + return day.isSame(this.props.value[1], 'day'); + } else if ( + Array.isArray(this.props.value) && + this.props.value.length >= 1 && + this.props.value[0] + ) { + return day.isSame(this.props.value[0], 'day'); + } else if (!Array.isArray(this.props.value) && this.props.value) { + return day.isSame(this.props.value, 'day'); + } + } + return false; + } + render() { + var that = this; + var last_week = -1; + return ( +
this.props.onClick && this.props.onClick()} + onMouseDown={this.props.onMouseDown} + > +
+
{moment(this.state.currentDate).format('MMMM YYYY')}
+
+
{ + this.setState(this.updateDay(moment(this.state.currentDate).subtract(1, 'months'))); + }} + > + +
+
{ + this.setState(this.updateDay(moment(this.state.currentDate).add(1, 'months'))); + }} + > + +
+
+
+
+
+ Wk +
+ {this.state.days.map((day, index) => { + if (index < 7) { + return ( +
+ {day.format('ddd')} +
+ ); + } + })} + {this.state.days.map((day, index) => { + var list = []; + if (day.week() != last_week) { + last_week = day.week(); + list.push(
{last_week}
); + } + list.push( +
{ + if (this.props.onChange) { + this.props.onChange(day); + } + }} + className={ + 'day ' + + (day.month() == this.state.currentDate.month() ? '' : 'notInMonth') + + ' ' + + (day.format('YYYY MM DD') == moment().format('YYYY MM DD') ? 'today' : '') + + ' ' + + (this.isSelected(day) ? 'selected' : '') + + ' ' + + (this.isLast(day) ? 'last' : '') + } + > + {day.date()} +
, + ); + return list; + })} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/Calendar/DayPicker/DayPicker.scss b/twake/frontend/src/app/components/calendar/day-picker/day-picker.scss similarity index 100% rename from twake/frontend/src/app/components/Calendar/DayPicker/DayPicker.scss rename to twake/frontend/src/app/components/calendar/day-picker/day-picker.scss diff --git a/twake/frontend/src/app/components/calendar/event/event.js b/twake/frontend/src/app/components/calendar/event/event.js new file mode 100755 index 0000000000..8ce56fb798 --- /dev/null +++ b/twake/frontend/src/app/components/calendar/event/event.js @@ -0,0 +1,136 @@ +import React, { Component } from 'react'; +import './event.scss'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Icon from 'components/icon/icon.js'; +import CalendarService from 'app/deprecated/Apps/Calendar/Calendar.js'; +import Languages from 'app/features/global/services/languages-service'; +import UserListManager from 'components/user-list-manager-depreciated/user-list-manager'; + +import moment from 'moment'; + +export default class Event extends React.Component { + constructor(props) { + super(); + this.props = props; + } + render() { + var className = ''; + var hiddenClass = ''; + var icon = ''; + var date; + var icon_location = ''; + var icon_description = ''; + var event_duration = ''; + var count = 0; + var style; + var classNameUser = ''; + if (this.props.inEvent) { + classNameUser = 'inEvent'; + } + + var event_name = + this.props.event.title || Languages.t('scenes.apps.drive.navigators.new_file.untitled'); + + var event_start = moment(parseInt(this.props.event.from) * 1000).format('LT'); + + var event_end = moment(parseInt(this.props.event.to) * 1000).format('LT'); + + var location = this.props.event.location || ''; + + var description = this.props.event.description; + + if (description) icon_description = 'subject'; + if (location) icon_location = 'location-point'; + + if (event_start) event_duration = event_start; + if (event_end) + event_duration = + event_duration + Languages.t('components.calendar.event.to', [], ' à ') + event_end; + + var duration = (parseInt(this.props.event.to) - parseInt(this.props.event.from)) / 60; + + if ( + (duration > 0 && duration <= 15) || + this.props.event.type == 'deadline' || + this.props.event.type == 'remind' + ) { + className += ' size_15 '; + } else if ((duration > 15 && duration <= 30) || this.props.event.all_day) { + className += ' size_30'; + if (location) event_duration += ', ' + location; + } else if (duration > 30 && duration <= 45) { + className += ' size_45'; + } else if (duration > 45 && duration <= 60) { + className += ' size_60'; + } + + className += ' ' + this.props.event.type; + + if (this.props.event.type == 'remind') { + icon = 'stopwatch'; + } else if (this.props.event.type == 'deadline') { + icon = 'stopwatch-slash'; + } else if (this.props.event.type == 'move') { + icon = 'car-sideview'; + } + + var readonly = CalendarService.getIsReadonly(this.props.event); + + var users = []; + var emails = []; + + (this.props.event.participants || []).map(obj => { + if (obj) { + var regex = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i; + if (obj.user_id_or_mail.match(regex)) { + var user = Collections.get('users').find(obj.user_id_or_mail); + users.push(user); + } else { + var email = obj.user_id_or_mail; + emails.push(email); + } + } + }); + + return ( +
+
+ {icon && } + + + {event_name} + + {(duration <= 30 || this.props.event.all_day) && ', ' + event_start} + + +
+ + {duration > 30 && !this.props.event.all_day && ( +
+ {event_duration} +
+ )} + +
+ {'' + location} +
+ +
+ { + return { id: u.user_id_or_mail }; + })} + max={4} + readOnly + collapsed + medium + /> +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/Calendar/Event/Event.scss b/twake/frontend/src/app/components/calendar/event/event.scss similarity index 100% rename from twake/frontend/src/app/components/Calendar/Event/Event.scss rename to twake/frontend/src/app/components/calendar/event/event.scss diff --git a/twake/frontend/src/app/components/calendar/time-selector.js b/twake/frontend/src/app/components/calendar/time-selector.js new file mode 100755 index 0000000000..b31d4ab064 --- /dev/null +++ b/twake/frontend/src/app/components/calendar/time-selector.js @@ -0,0 +1,119 @@ +import React, { Component } from 'react'; +import Input from 'components/inputs/input.js'; +import Tooltip from 'components/tooltip/tooltip.js'; +import moment from 'moment'; +import DateTimeUtils from 'app/features/global/utils/datetime.js'; +import Languages from 'app/features/global/services/languages-service'; + +export default class TimeSelector extends React.Component { + constructor(props) { + super(props); + this.state = { + time_ts: props.ts, + time_string: moment(new Date(props.ts * 1000)).format(DateTimeUtils.getDefaultTimeFormat()), + }; + this.old_ts = props.ts; + this.focus = false; + } + + shouldComponentUpdate(nextProps, nextStates) { + if (nextProps.ts != this.old_ts) { + this.old_ts = nextProps.ts; + nextStates.time_ts = nextProps.ts; + if (!this.focus) { + nextStates.time_string = moment(new Date(nextProps.ts * 1000)).format( + DateTimeUtils.getDefaultTimeFormat(), + ); + } + } + return true; + } + + process(string) { + var h, m, am_pm; + var error = false; + + if (string) { + var match = string.match(/^[^0-9]*([0-9]+)([^0-9]+)?([0-9]*)?(.*?)$/); + + if (match) { + h = parseInt(match[1]); + m = parseInt(match[3] || '0'); + am_pm = ((match[4] ? match[4] : match[2]) || '').toLocaleLowerCase(); + if (am_pm && (am_pm[0] == 'p' || am_pm.indexOf('pm') >= 0)) { + am_pm = 'PM'; + } else if (am_pm && (am_pm[0] == 'a' || am_pm.indexOf('am') >= 0)) { + am_pm = 'AM'; + } else { + if (h == 12) { + am_pm = 'PM'; + } else { + am_pm = 'AM'; + } + } + } else { + error = true; + } + + if (h > 12) { + am_pm = ''; + } + + if (h > 23) { + error = true; + } + + if (m > 59) { + error = true; + } + } else { + error = true; + } + + this.state.time_string = string; + + if (!error) { + var d = moment(h + ':' + m + am_pm, 'LT').toDate(); + var date = new Date(this.state.time_ts * 1000); + date.setHours(d.getHours()); + date.setMinutes(d.getMinutes()); + this.state.time_ts = date.getTime() / 1000; + this.state.error = false; + this.state.time_string_formatted = moment(this.state.time_ts * 1000).format( + DateTimeUtils.getDefaultTimeFormat(), + ); + this.props.onChange && this.props.onChange(this.state.time_ts); + } else { + this.state.error = true; + } + this.setState({}); + } + + blur() { + this.focus = false; + this.setState({ time_string: this.state.time_string_formatted, error: false }); + this.props.onChangeBlur && this.props.onChangeBlur(this.state.time_ts); + this.props.onChange && this.props.onChange(this.state.time_ts); + } + + render() { + return ( +
+ + this.blur()} + onFocus={() => (this.focus = true)} + value={this.state.time_string} + style={{ maxWidth: 94 }} + onChange={evt => this.process(evt.target.value)} + /> + +
+ ); + } +} diff --git a/twake/frontend/src/app/components/channel-attachement-list/channel-attachement-list.tsx b/twake/frontend/src/app/components/channel-attachement-list/channel-attachement-list.tsx new file mode 100644 index 0000000000..0a62132e63 --- /dev/null +++ b/twake/frontend/src/app/components/channel-attachement-list/channel-attachement-list.tsx @@ -0,0 +1,44 @@ +import { Modal, ModalContent } from 'app/atoms/modal'; +import { + channelAttachmentListState, + activeChannelAttachementListTabState, +} from 'app/features/channels/state/channel-attachment-list'; +import Languages from 'app/features/global/services/languages-service'; +import Tab from 'app/molecules/tabs'; +import React from 'react'; +import { useRecoilState } from 'recoil'; +import ChannelFiles from './parts/channel-files'; +import ChannelMedias from './parts/channel-medias'; + +enum Tabs { + Medias = 0, + Files = 1, +} + +export default (): React.ReactElement => { + const [open, setOpen] = useRecoilState(channelAttachmentListState); + const [activeTab, setActiveTab] = useRecoilState(activeChannelAttachementListTabState); + + return ( + setOpen(false)} className="sm:w-[60vw] sm:max-w-2xl"> + + +
+ {Languages.t('components.channel_attachement_list.medias')} +
+
, +
+
{Languages.t('components.channel_attachement_list.files')}
+
, + ]} + selected={activeTab} + onClick={index => setActiveTab(index)} + /> + {activeTab === Tabs.Medias && } + {activeTab === Tabs.Files && } + + + ); +}; diff --git a/twake/frontend/src/app/components/channel-attachement-list/parts/channel-attachment.tsx b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-attachment.tsx new file mode 100644 index 0000000000..2f0e531fd0 --- /dev/null +++ b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-attachment.tsx @@ -0,0 +1,173 @@ +import { Button } from 'app/atoms/button/button'; +import { DownloadIcon } from 'app/atoms/icons-agnostic'; +import { + FileTypeArchiveIcon, + FileTypeDocumentIcon, + FileTypePdfIcon, + FileTypeSpreadsheetIcon, + FileTypeUnknownIcon, +} from 'app/atoms/icons-colored'; +import { Base, Info } from 'app/atoms/text'; +import { channelAttachmentListState } from 'app/features/channels/state/channel-attachment-list'; +import fileUploadApiClient from 'app/features/files/api/file-upload-api-client'; +import fileUploadService from 'app/features/files/services/file-upload-service'; +import { formatDate } from 'app/features/global/utils/format-date'; +import { formatSize } from 'app/features/global/utils/format-file-size'; +import { Message, MessageFileType } from 'app/features/messages/types/message'; +import routerService from 'app/features/router/services/router-service'; +import { UserType } from 'app/features/users/types/user'; +import { useFileViewerModal } from 'app/features/viewer/hooks/use-viewer'; +import Media from 'app/molecules/media'; +import React from 'react'; +import { ArrowRight } from 'react-feather'; +import { useRecoilState } from 'recoil'; + +type FileMessageType = { + message?: Message; +}; + +type FileUserType = { + user?: UserType; +}; + +type PropsType = { + file: MessageFileType & FileMessageType & FileUserType; + is_media: boolean; +}; + +type FilePreviewType = { + file: MessageFileType & FileMessageType & FileUserType; +}; + +export default ({ file, is_media }: PropsType): React.ReactElement => { + return is_media ? : ; +}; + +const ChannelFile = ({ file }: FilePreviewType): React.ReactElement => { + const [, setOpen] = useRecoilState(channelAttachmentListState); + const name = file?.metadata?.name; + const extension = name?.split('.').pop(); + const previewUrl = fileUploadApiClient.getFileThumbnailUrlFromMessageFile(file); + const fileType = fileUploadApiClient.mimeToType(file?.metadata?.mime || ''); + const { open: openViewer } = useFileViewerModal(); + + const iconClassName = previewUrl + ? 'absolute left-0 top-0 bottom-0 right-0 m-auto w-8 h-8' + : 'absolute bottom-1 left-1 w-6 h-6'; + + return ( +
openViewer(file)} + > +
+ + {(!['image', 'video'].includes(fileType) || !previewUrl) && ( + <> + {fileType === 'archive' ? ( + + ) : fileType === 'pdf' ? ( + + ) : fileType === 'document' ? ( + + ) : fileType === 'slides' ? ( + + ) : ( + + )} + + )} +
+
+ {name} + + {extension?.toLocaleUpperCase()} • {formatDate(file?.message?.created_at)} •{' '} + {formatSize(file?.metadata?.size)} + +
+
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + + + {!!file.message && ( + + )} +
+
+ ); +}; + +const ChannelMedia = ({ file }: FilePreviewType): React.ReactElement => { + const previewUrl = fileUploadApiClient.getFileThumbnailUrlFromMessageFile(file); + const type = fileUploadApiClient.mimeToType(file?.metadata?.mime || ''); + const { open: openViewer } = useFileViewerModal(); + + return ( +
openViewer(file)} + > + +
+ ); +}; + +const getFileDownloadRoute = (file: MessageFileType): string => { + if (file?.metadata?.source !== 'internal') { + return ''; + } + + return fileUploadService.getDownloadRoute({ + companyId: file.metadata?.external_id?.company_id, + fileId: file.metadata?.external_id?.id, + }); +}; + +const downloadFile = (file: MessageFileType): void => { + const url = getFileDownloadRoute(file); + + if (url) { + window.location.href = url; + } +}; + +const gotoMessage = (message: Message): void => { + routerService.push( + routerService.generateRouteFromState({ + companyId: message?.cache?.company_id, + channelId: message?.cache?.channel_id, + threadId: message?.thread_id, + workspaceId: message?.cache?.workspace_id, + ...(message.id !== message?.thread_id ? { messageId: message.id } : {}), + }), + ); +}; diff --git a/twake/frontend/src/app/components/channel-attachement-list/parts/channel-files.tsx b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-files.tsx new file mode 100644 index 0000000000..ba273508ba --- /dev/null +++ b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-files.tsx @@ -0,0 +1,36 @@ +import { useChannelFileList } from 'app/features/channels/hooks/use-channel-media-files'; +import React, { useEffect } from 'react'; +import ChannelAttachment from './channel-attachment'; +import { LoadingAttachements, NoAttachements } from './commun'; +import PerfectScrollbar from 'react-perfect-scrollbar'; + +type PropsType = { + maxItems?: number; +}; + +export default ({ maxItems }: PropsType): React.ReactElement => { + const { loading, result, loadMore, loadItems } = useChannelFileList(); + + useEffect(() => { + loadItems(); + }, []); + + return ( + loadMore()} + > + {result.length === 0 && !loading && } + {loading ? ( + + ) : ( + result + .slice(0, maxItems || result.length) + .map(file => ) + )} + + ); +}; diff --git a/twake/frontend/src/app/components/channel-attachement-list/parts/channel-medias.tsx b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-medias.tsx new file mode 100644 index 0000000000..8404d77cac --- /dev/null +++ b/twake/frontend/src/app/components/channel-attachement-list/parts/channel-medias.tsx @@ -0,0 +1,44 @@ +import { useChannelMediaList } from 'app/features/channels/hooks/use-channel-media-files'; +import fileUploadApiClient from 'app/features/files/api/file-upload-api-client'; +import React, { useEffect } from 'react'; +import ChannelAttachment from './channel-attachment'; +import { LoadingAttachements, NoAttachements } from './commun'; +import PerfectScrollbar from 'react-perfect-scrollbar'; + +type PropsType = { + maxItems?: number; +}; + +export default ({ maxItems }: PropsType): React.ReactElement => { + const { loading, result, loadMore, loadItems } = useChannelMediaList(); + + useEffect(() => { + loadItems(); + }, []); + + return ( + <> + loadMore()} + > + {result.length === 0 && !loading && } + {loading ? ( + + ) : ( + result + .slice(0, maxItems || result.length) + .map(file => { + const url = fileUploadApiClient.getFileThumbnailUrlFromMessageFile(file); + + return url && ; + }) + .filter(Boolean) + )} + + + ); +}; diff --git a/twake/frontend/src/app/components/channel-attachement-list/parts/commun.tsx b/twake/frontend/src/app/components/channel-attachement-list/parts/commun.tsx new file mode 100644 index 0000000000..24ba522826 --- /dev/null +++ b/twake/frontend/src/app/components/channel-attachement-list/parts/commun.tsx @@ -0,0 +1,22 @@ +import { Loader } from 'app/atoms/loader'; +import { Info } from 'app/atoms/text'; +import Languages from 'app/features/global/services/languages-service'; +import React from 'react'; + +export const LoadingAttachements = (): React.ReactElement => { + return ( +
+ +
+ ); +}; + +export const NoAttachements = (): React.ReactElement => { + return ( +
+ + {Languages.t('components.channel_attachement_list.nothing_found')} + +
+ ); +}; diff --git a/twake/frontend/src/app/components/channel-members-list/channel-members-modal.tsx b/twake/frontend/src/app/components/channel-members-list/channel-members-modal.tsx new file mode 100644 index 0000000000..c0398c6812 --- /dev/null +++ b/twake/frontend/src/app/components/channel-members-list/channel-members-modal.tsx @@ -0,0 +1,177 @@ +import { InformationCircleIcon, MailOpenIcon } from '@heroicons/react/outline'; +import { PlusIcon, SearchIcon } from '@heroicons/react/solid'; +import { Alert } from 'app/atoms/alert'; +import { Button } from 'app/atoms/button/button'; +import { ButtonConfirm } from 'app/atoms/button/confirm'; +import { InputDecorationIcon } from 'app/atoms/input/input-decoration-icon'; +import { Input } from 'app/atoms/input/input-text'; +import { Info } from 'app/atoms/text'; +import { usePendingEmail } from 'app/features/channel-members-search/hooks/use-pending-email-hook'; +import { useSearchChannelMembersAll } from 'app/features/channel-members-search/hooks/use-search-all'; +import Languages from 'app/features/global/services/languages-service'; +import { delayRequest } from 'app/features/global/utils/managedSearchRequest'; +import Strings from 'app/features/global/utils/strings'; +import useRouterChannel from 'app/features/router/hooks/use-router-channel'; +import { useEffect, useState } from 'react'; +import PerfectScrollbar from 'react-perfect-scrollbar'; +import { EmailItem } from './email-item'; +import { MemberItem } from './member-item'; +import { UserItem } from './user-item'; + +export const ChannelMembersListModal = (): JSX.Element => { + const channelId = useRouterChannel(); + const [query, setQuery] = useState(''); + + const { addEmailSuggestion, pendingEmailList, channelMembersList, usersList, search, refresh } = + useSearchChannelMembersAll({ + channelId, + }); + + useEffect(() => { + delayRequest('ChannelMembersListModal', async () => { + search(query); + }); + }, [search, query]); + + useEffect(() => { + if (channelId) refresh(); + }); + + return ( +
+
+ ( + { + setQuery(e.target.value); + }} + value={query} + /> + )} + /> + {pendingEmailList?.length === 0 && channelMembersList?.length <= 1 && ( + + )} +
+
+ +
+ {addEmailSuggestion && + pendingEmailList?.length === 0 && + channelMembersList?.length === 0 && + usersList?.length === 0 && + !Strings.verifyMail(query) && ( + <> + + {Languages.t( + 'scenes.client.channelbar.channelmemberslist.search_invite_type_email', + )} + + + )} + {addEmailSuggestion && } + {pendingEmailList?.length > 0 && ( + <> + + {Languages.t('scenes.client.channelbar.channelmemberslist.pending_section')} + + + )} + {pendingEmailList && + pendingEmailList.map((item, index) => { + return ( +
+ +
+ ); + })} + {channelMembersList?.length > 0 && ( + <> + + {Languages.t('scenes.client.channelbar.channelmemberslist.members_section')} + + + )} + {channelMembersList && + channelMembersList + .filter(a => a && a?.user) + .map(cMember => { + return ( +
+ +
+ ); + })} + {usersList?.length > 0 && ( + <> + + {Languages.t('scenes.client.channelbar.channelmemberslist.not_members_section')} + + + )} + {usersList && + usersList.map(user => { + return ( +
+ +
+ ); + })} +
+
+
+
+ ); +}; + +const EmailSuggestion = ({ email }: { email: string }) => { + const { addInvite } = usePendingEmail(email); + + if (!email || !Strings.verifyMail(email)) { + return <>; + } + + return ( +
+ + {email} + + +
+ addInvite('member')} + > + {Languages.t('scenes.client.channelbar.channelmemberslist.invite_email_button_workspace')} + +
+ ); +}; diff --git a/twake/frontend/src/app/components/channel-members-list/email-item.tsx b/twake/frontend/src/app/components/channel-members-list/email-item.tsx new file mode 100644 index 0000000000..a374172501 --- /dev/null +++ b/twake/frontend/src/app/components/channel-members-list/email-item.tsx @@ -0,0 +1,106 @@ +import { MailIcon } from '@heroicons/react/outline'; +import { XIcon } from '@heroicons/react/solid'; +import { Tooltip } from 'antd'; +import { Button } from 'app/atoms/button/button'; +import { Modal, ModalContent } from 'app/atoms/modal'; +import { Info } from 'app/atoms/text'; +import { usePendingEmail } from 'app/features/channel-members-search/hooks/use-pending-email-hook'; +import Languages from 'app/features/global/services/languages-service'; +import { PendingEmail } from 'app/features/pending-emails/types/pending-email'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import useRouterWorkspace from 'app/features/router/hooks/use-router-workspace'; +import WorkspaceUserAPIClient from 'app/features/workspace-members/api/workspace-members-api-client'; +import { WorkspacePendingUserType } from 'app/features/workspaces/types/workspace'; +import { useState } from 'react'; + +type IProps = { + email: PendingEmail; +}; + +export const EmailItem = (props: IProps): JSX.Element => { + const { email } = props.email; + const { loading, cancelInvite } = usePendingEmail(email); + const workspaceId = useRouterWorkspace(); + const companyId = useRouterCompany(); + const [cancelWorkspaceInvitation, setCancelWorkspaceInvitation] = + useState(null); + + const _cancelInvite = async () => { + //Also check if the user is pending in the workspace and display something if that's the case + const pending = await WorkspaceUserAPIClient.listPending(companyId, workspaceId); + const foundWorkspacePending = pending.find( + p => p.email.toLocaleLowerCase() === email.toLocaleLowerCase(), + ); + if (foundWorkspacePending) { + //Propose to also cancel workspace invitation + setCancelWorkspaceInvitation(foundWorkspacePending); + } else { + await cancelInvite(); + } + }; + + return ( + <> + setCancelWorkspaceInvitation(null)}> + { + setCancelWorkspaceInvitation(null); + cancelInvite(); + }} + > + {Languages.t('general.no')} + , + , + ]} + > + +
+ +
+ + {email}{' '} + + ( + {Languages.t( + 'scenes.client.channels_bar.modals.parts.channel_member_row.label.pending_email', + )} + ) + + +
+
+
+ + + +
+ + ); +}; diff --git a/twake/frontend/src/app/components/channel-members-list/member-item.tsx b/twake/frontend/src/app/components/channel-members-list/member-item.tsx new file mode 100644 index 0000000000..c7ad9c7f56 --- /dev/null +++ b/twake/frontend/src/app/components/channel-members-list/member-item.tsx @@ -0,0 +1,81 @@ +import Avatar from 'app/atoms/avatar'; +import { ChannelMemberWithUser } from 'app/features/channel-members-search/types/channel-members'; +import Languages from 'app/features/global/services/languages-service'; +import UsersService from 'app/features/users/services/current-user-service'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import useRouterWorkspace from 'app/features/router/hooks/use-router-workspace'; +import useRouterChannel from 'app/features/router/hooks/use-router-channel'; +import { useChannelMember } from 'app/features/channel-members-search/hooks/member-hook'; +import { LogoutIcon } from '@heroicons/react/outline'; +import { Tooltip } from 'antd'; +import { ButtonConfirm } from 'app/atoms/button/confirm'; +import MemberGrade from 'app/views/client/popup/WorkspaceParameter/Pages/WorkspacePartnerTabs/MemberGrade'; + +type IMemberProps = { + member: ChannelMemberWithUser; + userId?: string; +}; + +export const MemberItem = (props: IMemberProps): JSX.Element => { + const { member, userId } = props; + const { first_name, email } = member.user; + const companyId = useRouterCompany(); + const workspaceId = useRouterWorkspace(); + const channelId = useRouterChannel(); + + const parameters = { companyId, workspaceId, channelId }; + + const { leave, loading } = useChannelMember(userId || '', parameters); + + const isCurrentUser = (): boolean => { + const currentUserId: string = UsersService.getCurrentUserId(); + + return props.userId === currentUserId; + }; + + return ( + <> +
+ +
+
+
+ {first_name} + {email} +
+
+
+ c.company.id === companyId)?.role || ''} + workspaceRole={member.user.workspaces?.find(c => c.id === workspaceId)?.role || ''} + /> +
+
+ {isCurrentUser() ? ( + + leave(props.userId || '')} + /> + + ) : ( + + leave(props.userId || '')} + /> + + )} +
+ + ); +}; diff --git a/twake/frontend/src/app/components/channel-members-list/user-item.tsx b/twake/frontend/src/app/components/channel-members-list/user-item.tsx new file mode 100644 index 0000000000..81982c98a6 --- /dev/null +++ b/twake/frontend/src/app/components/channel-members-list/user-item.tsx @@ -0,0 +1,100 @@ +import Avatar from 'app/atoms/avatar'; +import UsersService from 'app/features/users/services/current-user-service'; +import { useUser } from 'app/features/users/hooks/use-user'; +import { Button } from 'app/atoms/button/button'; +import Languages from 'app/features/global/services/languages-service'; +import { useChannelMember } from 'app/features/channel-members-search/hooks/member-hook'; +import { PlusIcon } from '@heroicons/react/solid'; +import useRouterWorkspace from 'app/features/router/hooks/use-router-workspace'; +import React from 'react'; +import { Modal, ModalContent } from 'app/atoms/modal'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import ConsoleService from 'app/features/console/services/console-service'; +import MemberGrade from 'app/views/client/popup/WorkspaceParameter/Pages/WorkspacePartnerTabs/MemberGrade'; + +type IUserProps = { + userId: string; +}; + +export const UserItem = (props: IUserProps): JSX.Element => { + const { userId } = props; + const user = useUser(userId || ''); + const workspaceId = useRouterWorkspace(); + const companyId = useRouterCompany(); + const [confirmWorkspaceInvitation, setConfirmWorkspaceInvitation] = + React.useState(false); + + if (!user) { + return <>; + } + + const { addMember, loading } = useChannelMember(userId || ''); + const [full_name, avatar] = [UsersService.getFullName(user), UsersService.getThumbnail(user)]; + + const _addMember = () => { + if (!(user.workspaces || []).map(w => w.id).includes(workspaceId)) { + //Ask for confirmation to invite the user to the workspace first + setConfirmWorkspaceInvitation(true); + } else { + addMember(userId || ''); + } + }; + + return ( + <> + setConfirmWorkspaceInvitation(false)}> + setConfirmWorkspaceInvitation(false)}> + {Languages.t('general.no')} + , + , + ]} + > + + +
+ +
+
+
+ {full_name} + {user.email} +
+
+
+ c.company.id === companyId)?.role || ''} + workspaceRole={user.workspaces?.find(c => c.id === workspaceId)?.role || ''} + /> +
+
+
+ + ); +}; diff --git a/twake/frontend/src/app/components/channel-members-list/users-search-modal.tsx b/twake/frontend/src/app/components/channel-members-list/users-search-modal.tsx new file mode 100644 index 0000000000..cac846753e --- /dev/null +++ b/twake/frontend/src/app/components/channel-members-list/users-search-modal.tsx @@ -0,0 +1,21 @@ +import { Modal, ModalContent } from 'app/atoms/modal'; +import { useUsersSearchModal } from 'app/features/channel-members-search/state/search-channel-member'; +import Languages from 'app/features/global/services/languages-service'; +import useRouterChannel from 'app/features/router/hooks/use-router-channel'; +import { ChannelMembersListModal } from './channel-members-modal'; + +export default () => { + const { open, setOpen } = useUsersSearchModal(); + const channelId = useRouterChannel(); + + return ( + setOpen(false)} className="sm:w-[80vw] sm:max-w-xl"> + + + + + ); +}; diff --git a/twake/frontend/src/app/components/color-picker/color-picker.js b/twake/frontend/src/app/components/color-picker/color-picker.js new file mode 100755 index 0000000000..316d738a67 --- /dev/null +++ b/twake/frontend/src/app/components/color-picker/color-picker.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react'; +import './color-picker.scss'; +import CheckIcon from '@material-ui/icons/CheckOutlined'; + +export default class ColorPicker extends React.Component { + static colors = [ + '#D50000', + '#E67C73', + '#F4511E', + '#F6BF26', + '#33B679', + '#0B8043', + '#039BE5', + '#3F51B5', + '#7986CB', + '#8E24AA', + '#801515', + '#616161', + ]; + + /* + props = { + value : default color + onChange : called when a color is selected + } + */ + constructor(props) { + super(); + this.colors = ColorPicker.colors; + } + render() { + var showed_selected = this.colors.indexOf(this.props.value) >= 0; + var colors = this.colors; + if (!showed_selected) { + var colors = this.colors.concat([this.props.value]); + } + return ( +
+ {colors.map(color => { + return ( +
this.props.onChange(color)} + > + {this.props.value == color && } +
+ ); + })} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/ColorPicker/ColorPicker.scss b/twake/frontend/src/app/components/color-picker/color-picker.scss similarity index 100% rename from twake/frontend/src/app/components/ColorPicker/ColorPicker.scss rename to twake/frontend/src/app/components/color-picker/color-picker.scss diff --git a/twake/frontend/src/app/components/CompanyMessagesCounter/CompanyMessagesCounter.scss b/twake/frontend/src/app/components/company-messages-counter/company-messages-counter.scss similarity index 100% rename from twake/frontend/src/app/components/CompanyMessagesCounter/CompanyMessagesCounter.scss rename to twake/frontend/src/app/components/company-messages-counter/company-messages-counter.scss diff --git a/twake/frontend/src/app/components/company-messages-counter/company-messages-counter.tsx b/twake/frontend/src/app/components/company-messages-counter/company-messages-counter.tsx new file mode 100644 index 0000000000..51346ddf21 --- /dev/null +++ b/twake/frontend/src/app/components/company-messages-counter/company-messages-counter.tsx @@ -0,0 +1,71 @@ +import React, { useEffect, useState } from 'react'; +import { Col, Progress, Row, Typography } from 'antd'; +import './company-messages-counter.scss'; +import i18n from 'i18next'; + +import Languages from 'app/features/global/services/languages-service'; +import { useCurrentCompany } from 'app/features/companies/hooks/use-companies'; +import FeatureTogglesService, { + FeatureNames, +} from 'app/features/global/services/feature-toggles-service'; +import MessageHistoryService from 'app/features/messages/services/message-history-service'; +import consoleService from 'app/features/console/services/console-service'; + +const { Text, Title, Link } = Typography; +const CompanyMessagesCounter = () => { + const [messagesCount, setMessagesCount] = useState(1); + const companyMessagesLimit = MessageHistoryService.getLimitCompanyMessages(); + + const { company } = useCurrentCompany(); + + const companySubscriptionUrl = consoleService.getCompanySubscriptionUrl(company.id); + + const onClickLink = () => window.open(companySubscriptionUrl, 'blank'); + + useEffect(() => { + if (company) { + setMessagesCount(company.stats?.total_messages || 1); + } + }, [company]); + + return !FeatureTogglesService.isActiveFeatureName(FeatureNames.MESSAGE_HISTORY) ? ( + <> + + + + {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_header', [])} + + + {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_info', [ + Intl.NumberFormat(i18n.language).format(companyMessagesLimit), + ])} + +
+ + {Languages.t('scenes.app.channelsbar.currentuser.company_messages_counter_link', [])} + +
+ + + (messagesCount / 1000).toFixed(1) + 'k'} + percent={(messagesCount / companyMessagesLimit) * 100} + width={55} + /> + +
+ + ) : ( + <> + ); +}; +export default CompanyMessagesCounter; diff --git a/twake/frontend/src/app/components/components-tester/component-doc.js b/twake/frontend/src/app/components/components-tester/component-doc.js new file mode 100755 index 0000000000..34325f33e7 --- /dev/null +++ b/twake/frontend/src/app/components/components-tester/component-doc.js @@ -0,0 +1,58 @@ +import React, { Component } from 'react'; +import InputWithClipBoard from 'components/input-with-clip-board/input-with-clip-board.js'; +import './component-doc.scss'; + +export default class ComponentDoc extends React.Component { + constructor() { + super(); + } + render() { + return ( +
+
+ {this.props.title &&
{this.props.title}
} + {this.props.import && ( + + )} +
+
{this.props.children}
+
+ {this.props.properties && [ +
Properties
, + + + + + + + + + + {this.props.properties.map(property => { + return ( + + + + + + + ); + })} +
PropertyTypeDefaultDescription
{property[0]} + {property[1].split(',').map(item => ( + {item} + ))} + {property[2]}{property[3]}
, +
, +
, + ]} + + {this.props.infos && [ +
Infos
, +
{this.props.infos}
, + ]} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/ComponentsTester/ComponentDoc.scss b/twake/frontend/src/app/components/components-tester/component-doc.scss similarity index 100% rename from twake/frontend/src/app/components/ComponentsTester/ComponentDoc.scss rename to twake/frontend/src/app/components/components-tester/component-doc.scss diff --git a/twake/frontend/src/app/components/components-tester/components-tester.js b/twake/frontend/src/app/components/components-tester/components-tester.js new file mode 100755 index 0000000000..50603aa3ca --- /dev/null +++ b/twake/frontend/src/app/components/components-tester/components-tester.js @@ -0,0 +1,369 @@ +import React, { Component } from 'react'; +import Emojione from 'components/emojione/emojione'; +import Icon from 'components/icon/icon.js'; +import Menu from 'components/menus/menu.js'; +import MenusBodyLayer from 'components/menus/menus-body-layer.js'; +import AutoComplete from 'components/auto-complete/auto-complete'; +import UserPicker from 'components/user-picker/user-picker.js'; +import EmojiPicker from 'components/emoji-picker/emoji-picker.js'; + +import Directory from 'components/drive/directory.js'; +import File from 'components/drive/file'; +import DriveMultiSelector from 'components/drive/drive-multi-selector.js'; + +import Rounded from 'components/inputs/rounded.js'; + +import DraggableBodyLayer from 'components/draggable/draggable-body-layer.js'; + +import emojiService from 'app/components/rich-text-editor/emojis-service.js'; +import User from 'components/ui/user.js'; + +import AutoHeight from 'components/auto-height/auto-height.js'; +import Tooltip from 'components/tooltip/tooltip.js'; +import InputWithClipBoard from 'components/input-with-clip-board/input-with-clip-board.js'; + +import './components-tester.scss'; +import GroupInputs from './group/inputs.js'; + +export default class ComponentsTester extends React.Component { + constructor() { + super(); + this.state = { + autocompValue: '', + visible: false, + }; + } + render() { + return [ +
+
+
Test des composants
+
ctrl+alt+e pour revenir à Twake
+
+ + + +
+
Icones
+ +
+ Title +
+
+ Sub title +
+
+ Text +
+
+ +
+
Emojione
+
+ Title +
+
+ Subtitle +
+
+ Text +
+
+
+
Tooltip
+
+ (this.tooltip = o)} + tooltip={'toolltiiiiiiiiip'} + position={'top'} + overable={false} + > +
this is my tooltip top
+
+
+ +
+ +
this is my tooltip top
+
+
+
+ +
+
Input with clipboard
+
+ +
+
+ +
+
Menus
+ + salut
, + }, + ], + }, + { type: 'separator' }, + { type: 'text', text: 'Du texte' }, + ]} + > + Click here ! + +
+
+
Auto complete one line
+ { + cb( + [ + { + id: 1, + username: 'benoit', + mail: 'benoit.tallandier@g.a', + userimage: 'https://randomuser.me/api/portraits/men/40.jpg', + }, + { + id: 2, + username: 'romaric', + mail: 'romaric.mourgues@g.a', + userimage: 'https://randomuser.me/api/portraits/men/41.jpg', + }, + { + id: 3, + username: 'guillaume', + mail: 'romaric.mourgues@g.a', + userimage: 'https://randomuser.me/api/portraits/men/42.jpg', + }, + { + id: 4, + username: 'Amandine', + mail: 'romaric.mourgues@g.a', + userimage: 'https://randomuser.me/api/portraits/women/40.jpg', + }, + ].filter(function (item) { + if (item && item.username.indexOf(text) !== -1) { + return true; + } + return false; + }), + ); + }, + (text, cb) => { + cb(emojiService.search(text)); + }, + ]} + max={[5, 5]} + renderItemChoosen={[ + item => { + return '@' + (item || {}).username + ' '; + }, + item => { + return item.shortname + ' '; + }, + ]} + renderItem={[ + item => { + return ( +
+ +
+ ); + }, + item => { + return ( +
+ {item.shortname} +
+ ); + }, + ]} + regexHooked={[/\B@([\-+\w]*)$/, /\B:([\-+\w]{0}[\-+\w]*)$/]} + placeholder="Placeholder" + autoHeight + /> +
+
+
Multi-line input
+ + +
+
+
Users picker
+
In menu
+ this.setState({ users_picker_value: list })} + /> + ), + }, + ]} + > +
Open menu
+
+ +
+
+
Inline
+ + this.setState({ users_picker_value: list })} + inline + /> + +
+
Inline read only
+ + + +
+
Inline read only miniatures
+ + +
+
+
Emoji picker
+ }]}> + Click here ! + +
+ +
+ + +
Drive
+ +
+ TODO: Tester drag drop depuis ordinateur +
+ TODO: Faire apparaitre l'icone "drag + menu" au survol +
+ + +
+
Dossiers
+ + + + + + + + + +
+
+ +
Fichiers
+ + + + + + + + + +
+
+
+
, + , + , + ]; + } +} diff --git a/twake/frontend/src/app/components/ComponentsTester/ComponentsTester.scss b/twake/frontend/src/app/components/components-tester/components-tester.scss similarity index 100% rename from twake/frontend/src/app/components/ComponentsTester/ComponentsTester.scss rename to twake/frontend/src/app/components/components-tester/components-tester.scss diff --git a/twake/frontend/src/app/components/components-tester/group/inputs.js b/twake/frontend/src/app/components/components-tester/group/inputs.js new file mode 100755 index 0000000000..effcde1387 --- /dev/null +++ b/twake/frontend/src/app/components/components-tester/group/inputs.js @@ -0,0 +1,123 @@ +import React, { Component } from 'react'; + +import Checkbox from 'components/inputs/checkbox.js'; +import Switch from 'components/inputs/switch'; +import Button from 'components/buttons/button.js'; +import Input from 'components/inputs/input.js'; + +import StepCounter from 'components/step-counter/step-counter.js'; +import Languages from 'app/features/global/services/languages-service'; +import { lang } from 'moment'; + +export default class GroupInputs extends React.Component { + constructor() { + super(); + this.state = { + input: 'Example', + }; + } + render() { + return [ +
+
Formulaires
+ +
className="big"
+ this.setState({ input: evt.target.value })} + /> +
+ this.setState({ input: value })} + /> +
+ this.setState({ input: value })} + /> +
+ +
className="medium"
+ this.setState({ input: evt.target.value })} + /> +
+ this.setState({ input: value })} + /> +
+ this.setState({ input: value })} + /> +
+ +
className="small"
+ this.setState({ input: evt.target.value })} + /> +
+ this.setState({ input: value })} + /> +
+ this.setState({ input: value })} + /> +
+
, +
+
+ +
Create my company 3/4
+
+ {Languages.t( + 'scenes.app.workspaces.create_company.importations.title_1', + [], + 'Already working with digital tools? Import or integrate your tools now!', + )} +
+ {Languages.t( + 'scenes.app.workspaces.create_company.importations.title_2', + [], + 'No worries, you can do this later!', + )} +
+ +
+
+
What's your company name ?
+ this.setState({ company_name: evt.target.value })} + placeholder="Ex : Google, Aircall, Doctolib" + /> +
+
+ +
+
+
+
, + ]; + } +} diff --git a/twake/frontend/src/app/components/configurators/config-body-layer.js b/twake/frontend/src/app/components/configurators/config-body-layer.js new file mode 100755 index 0000000000..1330567834 --- /dev/null +++ b/twake/frontend/src/app/components/configurators/config-body-layer.js @@ -0,0 +1,120 @@ +import React from 'react'; + +import ConfiguratorsManager from 'app/deprecated/Configurators/ConfiguratorsManager.js'; +import Twacode from 'components/twacode/twacode'; +import WorkspacesApps from 'app/deprecated/workspaces/workspaces_apps.js'; +import CloseIcon from '@material-ui/icons/CloseOutlined'; +import './configurators.scss'; +import Blocks from '../../views/applications/messages/message/parts/Blocks'; + +/* + Where the configurators will be displayed, this component should be in app.js (menus should be over all elements of the page) +*/ +export default class ConfigBodyLayer extends React.Component { + constructor(props) { + super(); + this.state = {}; + ConfiguratorsManager.addListener(this); + } + componentWillUnmount() { + ConfiguratorsManager.removeListener(this); + clearTimeout(this.loading_interaction_timeout); + } + componentWillMount() { + this.generateData(); + } + shouldComponentUpdate(nextProps, nextState) { + this.generateData(); + var string = JSON.stringify(this.configurator); + if (string != this.saved) { + nextState.loading_interaction = false; + clearTimeout(this.loading_interaction_timeout); + this.saved = string; + return true; + } + return nextState.loading_interaction ? true : false; + } + generateData() { + if (ConfiguratorsManager.configurator_order.length == 0) { + this.configurator = null; + } + this.configurator = + ConfiguratorsManager.currentConfigurators[ + ConfiguratorsManager.configurator_order[ConfiguratorsManager.configurator_order.length - 1] + ]; + } + onAction(type, id, context, passives, evt) { + if (type == 'interactive_action') { + this.setState({ loading_interaction: true }); + clearTimeout(this.loading_interaction_timeout); + this.loading_interaction_timeout = setTimeout(() => { + this.setState({ loading_interaction: false }); + }, 5000); + var app_id = this.configurator.app.id; + var type = 'interactive_configuration_action'; + var event = id; + var data = { + interactive_context: context, + form: passives, + hidden_data: this.configurator.hidden_data, + configurator_id: this.configurator.id, + }; + WorkspacesApps.notifyApp(app_id, type, event, data); + } + } + render() { + if (!this.configurator) { + return ''; + } + + return ( +
+
+
+
+
+
+
{this.configurator.app.identity?.name}
+ + { + ConfiguratorsManager.closeConfigurator(this.configurator.app); + }} + /> +
+
+ + this.onAction(type, id, context, passives, evt) + } + allowAdvancedBlocks={true} + /> +
+
+
+
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/configurators/configurators.scss b/twake/frontend/src/app/components/configurators/configurators.scss new file mode 100755 index 0000000000..df002a5991 --- /dev/null +++ b/twake/frontend/src/app/components/configurators/configurators.scss @@ -0,0 +1,60 @@ +.config_modal { + height: 100%; + width: 100%; + background: rgba(255, 255, 255, 0.5); + position: absolute; + z-index: 200; + top: 0; + + .modal { + width: 0px; + height: 0px; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + .component { + background: white; + border-radius: var(--border-radius-base); + box-shadow: var(--box-shadow-base); + position: relative; + display: inline-flex; + flex-direction: column; + transform: translateX(-50%) translateY(-50%); + .header { + padding: 15px; + border-bottom: 1px solid #ddd; + display: flex; + + .app_logo { + height: 30px; + width: 30px; + background-size: contain; + background-position: center; + border-radius: var(--border-radius-base); + margin-right: 5px; + } + .app_name { + line-height: 30px; + flex: auto; + } + .close { + margin: 2px; + opacity: 0.5; + cursor: pointer; + &:hover { + opacity: 1; + } + } + } + .content { + flex: 1; + overflow: auto; + padding: 15px; + box-sizing: border-box; + } + } + } +} diff --git a/twake/frontend/src/app/components/ConnectionIndicator/ConnectionIndicator.scss b/twake/frontend/src/app/components/connection-indicator/connection-indicator.scss similarity index 100% rename from twake/frontend/src/app/components/ConnectionIndicator/ConnectionIndicator.scss rename to twake/frontend/src/app/components/connection-indicator/connection-indicator.scss diff --git a/twake/frontend/src/app/components/connection-indicator/connection-indicator.tsx b/twake/frontend/src/app/components/connection-indicator/connection-indicator.tsx new file mode 100644 index 0000000000..22d0c91108 --- /dev/null +++ b/twake/frontend/src/app/components/connection-indicator/connection-indicator.tsx @@ -0,0 +1,42 @@ +import React, { useEffect } from 'react'; +import './connection-indicator.scss'; +import ErrorOutlinedIcon from '@material-ui/icons/ErrorOutlined'; +import HourglassEmpty from '@material-ui/icons/HourglassEmpty'; +import CheckCircleIcon from '@material-ui/icons/CheckCircle'; +import Languages from 'app/features/global/services/languages-service'; +import { ConnectedState } from 'app/features/users/state/atoms/connected'; +import { useRecoilState } from 'recoil'; +import WebSocket, { WebsocketEvents } from 'app/features/global/types/websocket-types'; + +export default () => { + const [{ connected, reconnecting }, setState] = useRecoilState(ConnectedState); + + useEffect(() => { + WebSocket.get().on(WebsocketEvents.Disconnected, () => { + setState({ connected: false, reconnecting: false }); + }); + WebSocket.get().on(WebsocketEvents.Connected, () => { + setState({ connected: true, reconnecting: false }); + }); + }, [setState]); + + return ( +
+ {connected === false && reconnecting !== true && ( +
+ {Languages.t('general.connexion_status.disconnected')} +
+ )} + {connected === false && reconnecting === true && ( +
+ {Languages.t('general.connexion_status.connecting')} +
+ )} + {connected === true && ( +
+ {Languages.t('general.connexion_status.connected')} +
+ )} +
+ ); +}; diff --git a/twake/frontend/src/app/components/connectors-list-manager/connectors-list-manager.js b/twake/frontend/src/app/components/connectors-list-manager/connectors-list-manager.js new file mode 100755 index 0000000000..32df8effca --- /dev/null +++ b/twake/frontend/src/app/components/connectors-list-manager/connectors-list-manager.js @@ -0,0 +1,139 @@ +import React, { Component } from 'react'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import CloseIcon from '@material-ui/icons/CloseOutlined'; +import AddIcon from '@material-ui/icons/AddOutlined'; +import GearIcon from '@material-ui/icons/BuildOutlined'; +import Input from 'components/inputs/input.js'; +import './connectors-list-manager.scss'; +import Languages from 'app/features/global/services/languages-service'; +import WorkspacesApps from 'app/deprecated/workspaces/workspaces_apps.js'; +import { getCompanyApplication as getApplication } from 'app/features/applications/state/company-applications'; + +export default class ConnectorsListManager extends React.Component { + constructor(props) { + super(); + this.props = props; + this.state = { + connectors_ids: props.current.map(item => item.id || ''), + filtered: [], + input: '', + }; + } + filter(text) { + this.state.input = text; + var list = this.props.list; + var res = list + .filter(el => { + return el.identity.name.toLocaleLowerCase().indexOf(text.toLocaleLowerCase()) >= 0; + }) + .map(el => el); + this.setState({ filtered: res }); + } + componentDidMount() { + this.filter(''); + } + + renderLine(item, added) { + var id = item.id || item; + + item = getApplication(id); + + var text = ''; + var button = ''; + + text = ( +
+ {WorkspacesApps.getAppIconComponent(item)} + {item.identity.name} +
+ ); + + if (added) { + button = ( +
+ { + this.props.onConfig(item); + }} + /> + { + this.state.connectors_ids = this.state.connectors_ids.filter(id => + typeof item == 'string' ? item != id : item.id != id, + ); + this.setState({}); + this.props.onChange(this.state.connectors_ids); + }} + /> +
+ ); + } else { + button = ( +
+ { + this.state.connectors_ids.push(item.id || this.state.input.toLocaleLowerCase()); + this.setState({ input: '' }); + this.props.onChange(this.state.connectors_ids); + }} + /> +
+ ); + } + + return ( +
+ {text} + {button} +
+ ); + } + render() { + return ( +
+
+
+ {Languages.t('scenes.apps.tasks.connectors_menu', [], 'Connecteurs')} +
+
+ + {this.state.connectors_ids.length == 0 && ( +
+ {Languages.t('scenes.apps.tasks.no_connector', [], 'Aucun connecteurs.')} +
+ )} + {this.state.connectors_ids.map(id => { + return this.renderLine(id, true); + })} +
+
+ {Languages.t('components.connectorslistmanager.add_connectors')} +
+
+ +
+
+ this.filter(evt.target.value)} + /> +
+
+ + {this.state.filtered.slice(0, 5).map(item => { + if (this.state.connectors_ids.indexOf(item.id) >= 0) { + return ''; + } + return this.renderLine(item, false); + })} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/ConnectorsListManager/ConnectorsListManager.scss b/twake/frontend/src/app/components/connectors-list-manager/connectors-list-manager.scss similarity index 100% rename from twake/frontend/src/app/components/ConnectorsListManager/ConnectorsListManager.scss rename to twake/frontend/src/app/components/connectors-list-manager/connectors-list-manager.scss diff --git a/twake/frontend/src/app/components/debug/debug-state.tsx b/twake/frontend/src/app/components/debug/debug-state.tsx new file mode 100644 index 0000000000..0383d9c4b9 --- /dev/null +++ b/twake/frontend/src/app/components/debug/debug-state.tsx @@ -0,0 +1,93 @@ +import React from 'react'; +import { useRecoilCallback } from 'recoil'; + +interface TwakeDebugState { + dumpStateSnapshot?(): void; + get?(key: string): void; + getAllAtoms?(): void; +} + +const twakeDebugState: TwakeDebugState = {}; + +const useDebugRecoilState = () => { + /** + * Get the value of an atom by key + * + * @param {string} key - The key of the atom + * @returns {void} + */ + twakeDebugState.get = useRecoilCallback( + ({ snapshot }) => + async (key: string) => { + const allNodes = Array.from(snapshot.getNodes_UNSTABLE()); + const node = allNodes.find(node => node.key === key); + + if (node) { + console.debug(key, await snapshot.getPromise(node)); + } + }, + [], + ); + + /** + * Dump the current state of the application to a json file + * + * @returns {void} + */ + twakeDebugState.dumpStateSnapshot = useRecoilCallback( + ({ snapshot }) => + async () => { + const result: Record = { + localStorage: {}, + }; + + for (const node of snapshot.getNodes_UNSTABLE()) { + const value = await snapshot.getPromise(node); + + result[node.key] = value; + } + + for (const key of Object.keys(window.localStorage)) { + result.localStorage[key] = window.localStorage.getItem(key); + } + + const json = JSON.stringify(result, null, 2); + const blob = new Blob([json], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + + link.href = url; + link.download = `twake-state-${new Date().toISOString()}.json`; + + link.click(); + URL.revokeObjectURL(url); + }, + [], + ); + + /** + * lists the value of all atoms + * + * @returns {void} + */ + twakeDebugState.getAllAtoms = useRecoilCallback( + ({ snapshot }) => + async () => { + for (const node of snapshot.getNodes_UNSTABLE()) { + const value = await snapshot.getPromise(node); + + console.debug(node.key, value); + } + }, + [], + ); + + (window as any).twakeDebugState = twakeDebugState; +}; + + +export default (): React.ReactElement => { + useDebugRecoilState(); + + return <>; +}; diff --git a/twake/frontend/src/app/components/download-app-banner/download-app-banner.tsx b/twake/frontend/src/app/components/download-app-banner/download-app-banner.tsx new file mode 100644 index 0000000000..11c13d2ff6 --- /dev/null +++ b/twake/frontend/src/app/components/download-app-banner/download-app-banner.tsx @@ -0,0 +1,39 @@ +import React, { useEffect, useState } from 'react'; +import InitService from '../../features/global/services/init-service'; +import LocalStorage from '../../features/global/framework/local-storage-service'; +import DownloadBanner from 'app/molecules/download-banner'; +import { detectDesktopAppPresence } from '../../../utils/browser-detect'; + +export default (): React.ReactElement => { + const [showBanner, setShowBanner] = useState(false); + + const download = (): void => { + const appDownloadUrl = InitService?.server_infos?.configuration?.app_download_url; + + if (appDownloadUrl) { + window.open(appDownloadUrl, '_blank'); + } + }; + + const removeBanner = (): void => { + LocalStorage.setItem('show_app_banner', 'false'); + setShowBanner(false); + }; + + useEffect(() => { + if (LocalStorage.getItem('show_app_banner') === 'false') { + setShowBanner(false); + return; + } + + detectDesktopAppPresence().then(detected => { + if (!detected && LocalStorage.getItem('show_app_banner') === null) { + setShowBanner(true); + } else { + LocalStorage.setItem('show_app_banner', 'false'); + } + }); + }, []); + + return showBanner ? : <>; +}; diff --git a/twake/frontend/src/app/components/draggable/draggable-body-layer.js b/twake/frontend/src/app/components/draggable/draggable-body-layer.js new file mode 100755 index 0000000000..ef47e021b5 --- /dev/null +++ b/twake/frontend/src/app/components/draggable/draggable-body-layer.js @@ -0,0 +1,23 @@ +import React, { Component } from 'react'; + +import DraggableManager from './draggable-manager.js'; + +export default class DraggableBodyLayer extends React.Component { + constructor(props) { + super(); + this.state = { + draggable_manager: DraggableManager, + }; + this.draggable_body_dom = null; + DraggableManager.addListener(this); + } + componentDidMount() { + DraggableManager.registerContainer(this.draggable_body_dom); + } + componentWillUnmount() { + DraggableManager.removeListener(this); + } + render() { + return
(this.draggable_body_dom = node)} />; + } +} diff --git a/twake/frontend/src/app/components/draggable/draggable-manager.js b/twake/frontend/src/app/components/draggable/draggable-manager.js new file mode 100755 index 0000000000..9af86534cd --- /dev/null +++ b/twake/frontend/src/app/components/draggable/draggable-manager.js @@ -0,0 +1,238 @@ +import React, { Component } from 'react'; + +import Observable from 'app/deprecated/CollectionsV1/observable.js'; +import SelectionsManager from 'app/deprecated/SelectionsManager/SelectionsManager.js'; + +class DraggableManager extends Observable { + constructor() { + super(); + this.setObservableName('draggable_manager'); + this.container = null; + + this.move = this.move.bind(this); + this.end = this.end.bind(this); + this.start = this.start.bind(this); + + this.drag = false; + this.clone_created = false; + this.drag_initial_point = []; + this.current_node_initial_position = []; + } + + registerContainer(container) { + this.container = container; + } + + setDropCallback(key, callback) { + this.callback_key = key; + this.callback = callback; + } + + removeDropCallback(key) { + if (this.callback_key == key) { + this.callback = false; + this.callback_key = null; + } + } + + start(evt, node, react_draggable) { + if (this.dragging) { + return; + } + + if (react_draggable.props.dragHandler) { + var onHandler = false; + var handlers = node.getElementsByClassName(react_draggable.props.dragHandler); + if (handlers.length > 0) { + Array.from(handlers).forEach(item => { + if (item == evt.target || item.contains(evt.target)) { + onHandler = true; + } + }); + } + + if (!onHandler) { + return; + } + } + + this.data = {}; + if (node) { + this.current_node = node; + } + if (react_draggable) { + this.current_react_draggable = react_draggable; + this.props = { + parentClassOnDrag: this.current_react_draggable.props.parentClassOnDrag, + minMove: this.current_react_draggable.props.minMove, + }; + this.data = this.current_react_draggable.props.data; + } + + this.selected_number = 1; + if (this.data.selection_type) { + this.selected_number = SelectionsManager.selected_per_type[this.data.selection_type]; + if (this.selected_number) { + this.selected_number = Object.keys(this.selected_number).length; + } + + if (!this.selected_number) { + this.selected_number = 1; + } + } + + evt.stopPropagation(); + evt.preventDefault(); + + document.addEventListener('mousemove', this.move); + document.addEventListener('mouseup', this.end); + var rect = window.getBoundingClientRect(this.current_node); + rect.x = rect.x || rect.left; + rect.y = rect.y || rect.top; + + this.clone_created = false; + this.drag_initial_point = [evt.clientX, evt.clientY]; + this.current_node_initial_position = [rect.left, rect.top, node.clientWidth, node.clientHeight]; + + this.drag = true; + if (this.current_react_draggable) this.current_react_draggable.setState({ drag: true }); + } + end(evt, node, react_draggable) { + if (this.dragging) { + evt.preventDefault(); + evt.stopPropagation(); + } + + this.current_react_draggable && this.current_react_draggable.setState({ hide_original: false }); + + if (!this.data) { + return; + } + + if (node) { + this.current_node = node; + } + if (react_draggable) { + this.current_react_draggable = react_draggable; + this.props = { + parentClassOnDrag: this.current_react_draggable.props.parentClassOnDrag, + minMove: this.current_react_draggable.props.minMove, + }; + } + + document.removeEventListener('mousemove', this.move); + document.removeEventListener('mouseup', this.end); + + document.body.classList.remove('dragging'); + document.body.classList.remove('drag_' + this.data.type); + this.drag = false; + this.dragging = false; + if (this.current_react_draggable) + this.current_react_draggable.setState({ drag: false, dragging: false }); + + var delete_delay = 0; + if (this.callback) { + this.callback(this.data); + } else { + if (this.clone) { + this.clone.style.transition = 'transform 0.2s'; + this.clone.style.transform = + 'translateX(' + + this.current_node_initial_position[0] + + 'px) translateY(' + + this.current_node_initial_position[1] + + 'px)'; + } + delete_delay = 200; + } + + setTimeout(() => { + if (this.clone) { + try { + this.container.removeChild(this.clone); + } catch (e) {} + } + if (this.current_react_draggable) + this.current_react_draggable.setState({ hide_original: false }); + if (this.props.parentClassOnDrag) { + this.props.parentClassOnDrag.split(' ').forEach(c => { + this.container.classList.remove(c); + }); + } + }, delete_delay); + + this.data = {}; + } + move(evt) { + if (!this.data) { + return; + } + + var deltaX = evt.clientX - this.drag_initial_point[0]; + var deltaY = evt.clientY - this.drag_initial_point[1]; + + if ( + !this.clone_created && + Math.max(Math.abs(deltaX), Math.abs(deltaY)) < (this.props.minMove || 10) + ) { + return; + } + + if (this.drag) { + if (!this.clone_created) { + var html = this.current_node.outerHTML; + var div = document.createElement('div'); + div.classList.add('draggable_clone'); + div.innerHTML = html.trim(); + div.firstChild.classList.remove('dragging_opacity'); + div.firstChild.classList.remove('fade_in'); + div.firstChild.classList.remove('is_selected'); + + div.style.width = this.current_node_initial_position[2] + 'px'; + div.style.height = this.current_node_initial_position[3] + 'px'; + + this.clone = div; + + if (this.selected_number > 1) { + var div_number = document.createElement('div'); + div_number.classList.add('draggable_number'); + div_number.innerHTML = this.selected_number; + this.clone.appendChild(div_number); + } + + this.container.appendChild(this.clone); + this.clone_created = true; + + if (this.props.parentClassOnDrag) { + this.props.parentClassOnDrag.split(' ').forEach(c => { + this.container.classList.add(c); + }); + } + + if ( + this.current_react_draggable && + this.current_react_draggable.props && + this.current_react_draggable.props.onDragStart + ) { + this.current_react_draggable.props.onDragStart(evt); + } + + this.dragging = true; + if (this.current_react_draggable) + this.current_react_draggable.setState({ dragging: true, hide_original: true }); + } + + document.body.classList.add('dragging'); + document.body.classList.add('drag_' + this.data.type); + this.clone.style.transform = + 'translateX(' + + (deltaX + this.current_node_initial_position[0]) + + 'px) translateY(' + + (deltaY + this.current_node_initial_position[1]) + + 'px)'; + } + } +} + +const service = new DraggableManager(); +export default service; diff --git a/twake/frontend/src/app/components/Draggable/Draggable.scss b/twake/frontend/src/app/components/draggable/draggable.scss similarity index 100% rename from twake/frontend/src/app/components/Draggable/Draggable.scss rename to twake/frontend/src/app/components/draggable/draggable.scss diff --git a/twake/frontend/src/app/components/draggable/draggable.tsx b/twake/frontend/src/app/components/draggable/draggable.tsx new file mode 100755 index 0000000000..0f7bc725e7 --- /dev/null +++ b/twake/frontend/src/app/components/draggable/draggable.tsx @@ -0,0 +1,42 @@ +// eslint-disable-next-line @typescript-eslint/no-use-before-define +import React from 'react'; +import './draggable.scss'; +import DraggableManager from './draggable-manager.js'; +import classNames from 'classnames'; + +type PropsType = { [key: string]: any }; + +type StateType = { [key: string]: any }; + +export default class Draggable extends React.Component { + node: HTMLDivElement | null | undefined; + + render() { + return ( +
{ + this.node = node; + if (this.props.refDraggable) { + this.props.refDraggable(node); + } + }} + onClick={this.props.onClick} + onMouseDown={evt => { + !this.props?.deactivated && DraggableManager.start(evt, this.node, this); + }} + onMouseUp={evt => { + !this.props?.deactivated && DraggableManager.end(evt, this.node, this); + }} + onMouseOver={this.props.onMouseOver} + onMouseOut={this.props.onMouseOut} + onDoubleClick={this.props.onDoubleClick} + > + {this.props.children} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/draggable/droppable-zone.js b/twake/frontend/src/app/components/draggable/droppable-zone.js new file mode 100755 index 0000000000..5ca965e66f --- /dev/null +++ b/twake/frontend/src/app/components/draggable/droppable-zone.js @@ -0,0 +1,73 @@ +import React, { Component } from 'react'; + +import DraggableManager from './draggable-manager.js'; +import Number from 'app/features/global/utils/Numbers'; +import './draggable.scss'; + +export default class DroppableZone extends React.Component { + constructor(props) { + super(); + this.unique_drop_key = Number.unid(); + this.longOverTimeout = ''; + } + onDrop(data) { + if (!data) { + return; + } + if (this.props.types && data.type) { + if (this.props.types.indexOf(data.type) < 0) { + return; + } + } + if (this.props.onDrop) { + this.props.onDrop(data); + } + } + componentWillUnmount() { + DraggableManager.removeDropCallback(this.unique_drop_key); + clearTimeout(this.longOverTimeout); + } + onEnter() { + if (DraggableManager.drag) { + this.longOverTimeout = setTimeout(() => { + if (DraggableManager.drag) { + if (this.props.onClick && !this.props.disableLongOver) { + this.props.onClick(); + } + if (this.props.onLongOver) { + this.props.onLongOver(); + } + } + }, 1500); + DraggableManager.setDropCallback(this.unique_drop_key, d => this.onDrop(d)); + } + } + onLeave() { + DraggableManager.removeDropCallback(this.unique_drop_key); + clearTimeout(this.longOverTimeout); + } + render() { + return ( +
{ + if (!this.props.deactivated) { + this.onEnter(); + } + }} + onMouseLeave={() => { + if (!this.props.deactivated) { + this.onLeave(); + } + }} + > + {this.props.children} + {!this.props.children && !this.props.deactivated && ( +
{this.props.empty || ''}
+ )} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/drive/directory.js b/twake/frontend/src/app/components/drive/directory.js new file mode 100755 index 0000000000..5e7def270f --- /dev/null +++ b/twake/frontend/src/app/components/drive/directory.js @@ -0,0 +1,87 @@ +import React from 'react'; +import DriveElement from './drive-element.js'; +import UIDirectory from './ui/directory.js'; +import Loader from 'components/loader/loader.js'; + +import WorkspaceUserRights from 'app/features/workspaces/services/workspace-user-rights-service'; +import Draggable from 'components/draggable/draggable'; +import DroppableZone from 'components/draggable/droppable-zone.js'; +import Languages from 'app/features/global/services/languages-service'; +import './drive.scss'; + +export default class Directory extends DriveElement { + constructor(props) { + super(); + this.props = props; + this.state = { + loading: true, + }; + } + componentDidMount() { + super.componentDidMount(); + if (this.state.loading) { + setTimeout(() => { + this.setState({ loading: false }); + }, 4000); + } + } + render() { + if (!this.state.element || !this.state.element.front_id) { + return ( +
+ {this.state.loading && } + {!this.state.loading && ( + + {Languages.t( + 'components.drive.navigators.directory_not_found', + [], + 'Directory not found.', + )} + + )} +
+ ); + } else { + this.state.loading = false; + } + + if (this.props.hide) { + return ''; + } + + return ( + this.dropFile(data)} + onLongOver={this.props.onClick} + className="directory_drop_zone" + > + (this.node = node)} + onClick={evt => { + this.clickElement(evt); + }} + onDoubleClick={this.props.onDoubleClick} + parentClassOnDrag="grid" + onDragStart={evt => { + this.dragElement(evt); + }} + minMove={10} + data={{ type: 'file', selection_type: this.props.selectionType, data: this.props.data }} + > + + + + ); + } +} diff --git a/twake/frontend/src/app/components/drive/drive-element.js b/twake/frontend/src/app/components/drive/drive-element.js new file mode 100755 index 0000000000..e7b4bb0b8f --- /dev/null +++ b/twake/frontend/src/app/components/drive/drive-element.js @@ -0,0 +1,645 @@ +import React, { useState } from 'react'; + +import SelectionsManager from 'app/deprecated/SelectionsManager/SelectionsManager.js'; +import DriveService from 'app/deprecated/Apps/Drive/Drive.js'; +import AlertManager from 'app/features/global/services/alert-manager-service'; +import MenuManager from 'app/components/menus/menus-manager.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import FilePicker from 'components/drive/file-picker/file-picker.js'; +import Button from 'components/buttons/button.js'; +import Input from 'components/inputs/input.js'; +import VersionDetails from './version-details.js'; +import WorkspacesApps from 'app/deprecated/workspaces/workspaces_apps.js'; +import InputWithClipBoard from 'components/input-with-clip-board/input-with-clip-board.js'; +import WorkspaceUserRights from 'app/features/workspaces/services/workspace-user-rights-service'; +import MediumPopupManager from 'app/components/modal/modal-manager'; +import Languages from 'app/features/global/services/languages-service'; +import TagPicker from 'components/tag-picker/tag-picker.js'; +import RouterServices from 'app/features/router/services/router-service'; +import { getAsFrontUrl } from 'app/features/global/utils/URLUtils'; +import FeatureTogglesService, { + FeatureNames, +} from 'app/features/global/services/feature-toggles-service'; +import ModalManager from 'app/components/modal/modal-manager'; +import InitService from 'app/features/global/services/init-service'; +import LockedOnlyOfficePopup from 'app/components/locked-features-components/locked-only-office-popup/locked-only-office-popup'; + +const RenameInput = props => { + const [value, setValue] = useState(props.value); + return ( +
+
+ { + if ((value || '').trim().length > 0) { + props.rename(value); + } + }} + className="full_width bottom-margin" + onEchap={() => { + MenuManager.closeMenu(); + }} + autoFocus + value={value} + onChange={evt => setValue(evt.target.value)} + /> +
+
+
+
+ ); +}; + +const PublicSharing = props => { + Collections.get('drive').useListener(useState); + const element = Collections.get('drive').find(props.id); + if (!element) { + return
; + } + const sharedUrl = RouterServices.generateRouteFromState({ + workspaceId: element.workspace_id, + documentId: element.id, + appName: 'drive', + shared: true, + token: (element.acces_info || {}).token, + }); + return ( +
+ {(element.acces_info || {}).token && ( +
+ +
+
+
+ )} + {!(element.acces_info || {}).token && ( +
+
+ )} +
+ ); +}; + +export default class DriveElement extends React.Component { + constructor(props) { + super(); + this.state = { + selections_manager: SelectionsManager, + }; + SelectionsManager.addListener(this); + + this.driveCollectionKey = ''; + + this.driveSelectorOver = this.driveSelectorOver.bind(this); + this.driveSelectorOut = this.driveSelectorOut.bind(this); + Collections.get('drive').addListener(this); + } + componentWillUnmount() { + SelectionsManager.removeListener(this); + Collections.get('drive').removeListener(this); + if (this.node) { + this.node.removeEventListener('drive_selector_over', this.driveSelectorOver); + this.node.removeEventListener('drive_selector_out', this.driveSelectorOut); + } + + if (this.driveCollectionKey && this.driveCollectionKey != this.props.driveCollectionKey) { + Collections.get('drive').removeSource(this.driveCollectionKey); + } + } + componentWillMount() { + if (this.props && this.props.data && this.props.data.front_id) { + Collections.get('drive').listenOnly(this, [this.props.data.front_id]); + } + + this.state.element = DriveService.find( + Workspaces.currentWorkspaceId, + this.props.data.id, + el => { + this.setState({ element: el }); + }, + ); + this.updateMenu(); + } + componentDidMount() { + if (this.node) { + this.node.addEventListener('drive_selector_over', this.driveSelectorOver); + this.node.addEventListener('drive_selector_out', this.driveSelectorOut); + this.node.setAttribute('drive_selector_unid', this.state.element.id); + } + + if (this.props && this.props.data && this.props.data.id) { + SelectionsManager.listenOnly(this, [this.props.data.id]); + } + } + driveSelectorOut() { + if (this.state.selected) this.setState({ selected: false }); + } + driveSelectorOver() { + if (!this.state.selected) this.setState({ selected: true }); + } + + dropFile(data, directory) { + var destination = directory || this.props.data; + + var objects = data.data.id; + if (data.selection_type) { + var selected = Object.keys(SelectionsManager.selected_per_type[data.selection_type] || {}); + if (selected && selected.length > 1) { + var objects = selected; + } + } + + DriveService.moveFile( + objects, + destination, + this.props.driveCollectionKey || this.driveCollectionKey, + ); + } + + dragElement(evt) { + SelectionsManager.setType(this.props.selectionType); + if ( + !evt.shiftKey && + !SelectionsManager.selected_per_type[this.props.selectionType][this.state.element.id] + ) { + SelectionsManager.unselectAll(); + } + SelectionsManager.select(this.state.element.id); + } + + clickElement(evt, previewonly = false) { + evt.stopPropagation(); + evt.preventDefault(); + + if (this.props.notInDrive) { + if (this.props.onClick) { + this.props.onClick(); + } else { + DriveService.viewDocument(this.state.element, previewonly); + } + } else { + SelectionsManager.setType(this.props.selectionType); + if (!evt.shiftKey) { + if (this.props.onClick) { + this.props.onClick(); + } else { + DriveService.viewDocument(this.state.element, previewonly); + } + + var oldStatus = + SelectionsManager.selected_per_type[this.props.selectionType][this.state.element.id]; + SelectionsManager.unselectAll(); + if (oldStatus) { + SelectionsManager.unselect(this.state.element.id); + } else { + SelectionsManager.select(this.state.element.id); + } + } else { + SelectionsManager.toggle(this.state.element.id); + } + } + } + componentWillUpdate(nextProps, nextState) { + nextState.element = + Collections.get('drive').find(this.props.data.id) || + DriveService.find(Workspaces.currentWorkspaceId, this.props.data.id, el => { + this.setState({ element: el }); + }); + this.state.element = nextState.element; + + if ( + this.state.element && + SelectionsManager.selected_per_type[nextProps.selectionType] && + SelectionsManager.selected_per_type[nextProps.selectionType][this.state.element.id] != + this.old_selection_state + ) { + nextState.selected = + SelectionsManager.selected_per_type[nextProps.selectionType][nextProps.data.id]; + this.old_selection_state = nextState.selected; + } + + if (this.state.element && !this.props.driveCollectionKey) { + this.channel = 'standalone_drive_collection_' + this.state.element.parent_id; + var parent_id = this.state.element.parent_id; + if (this.state.element.parent_id == 'detached') { + parent_id += '_' + this.state.element.workspace_id; + } + var old_collection_key = this.driveCollectionKey; + this.driveCollectionKey = DriveService.addSourceIfNotExist( + Workspaces.currentWorkspaceId, + this.channel, + parent_id, + 'standalone', + ); + if (old_collection_key && old_collection_key != this.driveCollectionKey) { + Collections.get('drive').removeSource(old_collection_key); + } + } + + this.updateMenu(); + + return true; + } + + moveTo(new_parent) { + DriveService.moveFile( + [this.state.element.id], + new_parent, + this.props.driveCollectionKey || this.driveCollectionKey, + ); + } + + rename(new_name) { + if (!this.state.element.is_directory) { + new_name = new_name + '.' + this.state.element.extension; + } + this.state.element.name = new_name || this.state.element.name; + new_name = undefined; + MenuManager.closeMenu(); + DriveService.save(this.state.element, this.props.driveCollectionKey || this.driveCollectionKey); + } + + updateMenu() { + if (!this.state.element) { + this.common_menu = []; + return; + } + + this.common_menu = []; + + //-- All files + if (!this.state.element.is_directory) { + this.common_menu = [ + { + type: 'menu', + text: Languages.t('components.drive.elements.see', [], 'Voir'), + onClick: () => { + DriveService.viewDocument(this.state.element); + }, + }, + ]; + + var candidates = DriveService.getEditorsCandidates(this.state.element); + var preview_candidate = candidates.editor_candidate || []; + var editor_candidate = candidates.preview_candidate || []; + + if (editor_candidate.length > 0 && editor_candidate[0].app) { + this.common_menu.push({ + type: 'menu', + text: Languages.t( + 'scenes.apps.drive.viewer.edit_with_button', + [editor_candidate[0].app.identity?.name], + 'Editer avec $1', + ), + onClick: () => { + if (FeatureTogglesService.isActiveFeatureName(FeatureNames.EDIT_FILES)) { + var app = editor_candidate[0]; + if (app.url && app.is_url_file) { + window.open(app.url); + } + var app = app.app; + DriveService.getFileUrlForEdition( + app.display?.twake?.files?.editor?.edition_url, + app, + this.state.element.id, + url => { + window.open(url); + }, + ); + } else { + ModalManager.open( + , + { + position: 'center', + size: { width: '600px' }, + }, + false, + ); + } + }, + }); + } + } + + this.common_menu.push({ + type: 'menu', + text: + this.state.element.url && this.state.element.extension == 'url' + ? Languages.t('scenes.apps.drive.open_link', [], 'Open link') + : Languages.t('scenes.apps.drive.download_button', [], 'Télécharger'), + onClick: () => { + var link = DriveService.getLink(this.state.element, undefined, 1); + if (this.state.element.url) { + window.open(link, '_blank'); + } else { + window.open(link); + } + }, + }); + + if (!WorkspaceUserRights.isNotConnected()) { + //-- All files + if (this.state.element.detached) { + this.common_menu.push({ + type: 'menu', + text: Languages.t('scenes.apps.drive.move_text2', [], 'Déplacer'), + submenu_replace: true, + submenu: [ + { + type: 'react-element', + reactElement: () => ( + this.moveTo(res)} + initialDirectory={{ id: '' }} + /> + ), + }, + ], + }); + } + + if (!this.props.notInDrive && !this.state.element.detached) { + if (this.common_menu.length > 0) { + this.common_menu.push({ type: 'separator' }); + } + + if (!this.state.element.detached && this.state.element.parent_id) { + this.common_menu = this.common_menu.concat([ + { + type: 'menu', + text: Languages.t('scenes.app.mainview.tabs.rename', [], 'Renommer'), + submenu_replace: true, + submenu: [ + { + type: 'title', + text: Languages.t('scenes.app.mainview.tabs.rename', [], 'Renommer'), + }, + { + type: 'text', + text: + Languages.t('components.drive.elements.current_name', [], 'Nom actuel : ') + + this.state.element.name, + }, + { + type: 'react-element', + reactElement: () => ( + { + this.rename(name); + }} + value={ + this.state.element.is_directory + ? this.state.element.name + : this.state.element.name.replace(/\.[^.]*$/, '') + } + /> + ), + }, + ], + }, + ]); + } + + if (!this.state.element.trash) { + this.common_menu = this.common_menu.concat([ + { + type: 'menu', + text: Languages.t('scenes.apps.drive.right_preview.public', [], 'Accès public...'), + submenu_replace: true, + submenu: [ + { + type: 'title', + text: Languages.t( + 'scenes.apps.drive.right_preview.public_link', + [], + "Lien d'accès public", + ), + }, + { + //TODO menu react-element to refactor + type: 'react-element', + reactElement: () => ( + + ), + }, + ], + }, + ]); + + if (!(this.state.element.application_id && this.state.element.is_directory)) { + this.common_menu.push({ + type: 'menu', + text: Languages.t('scenes.apps.drive.move_text', [], 'Déplacer'), + submenu_replace: true, + submenu: [ + { + type: 'react-element', + reactElement: () => ( + this.moveTo(res)} + initialDirectory={{ id: this.state.element.parent_id }} + /> + ), + }, + ], + }); + } + + if (WorkspaceUserRights.hasWorkspacePrivilege()) { + if (this.state.element.application_id && this.state.element.is_directory) { + this.common_menu.push({ + type: 'menu', + text: Languages.t( + 'components.drive.elements.configurate_mod', + [], + 'Configurer le module...', + ), + onClick: () => { + var data = { + drive_element: this.state.element, + }; + WorkspacesApps.notifyApp( + this.state.element.application_id, + 'configuration', + 'drive', + data, + ); + }, + }); + } + } + + if (!this.state.element.is_directory && !this.state.element.url) { + var versions_indicator = ''; + if ((this.state.element.versions || {}).length > 1) { + versions_indicator = ' (' + (this.state.element.versions || {}).length + ')'; + } + this.common_menu.push( + { + type: 'menu', + text: + Languages.t( + 'components.drive.elements.manage_version', + [], + 'Gérer les versions', + ) + + versions_indicator + + '...', + onClick: () => { + MediumPopupManager.open(, { + size: { width: 600 }, + }); + }, + }, + { + type: 'menu', + text: Languages.t( + 'scenes.apps.drive.navigators.navigator_labels.title', + [], + 'Labels', + ), + submenu_replace: true, + submenu: [ + { + type: 'title', + text: Languages.t( + 'scenes.apps.drive.navigators.navigator_labels.title', + [], + 'Labels', + ), + }, + { + type: 'react-element', + reactElement: level => ( +
+ { + this.state.element.tags = values; + MenuManager.closeMenu(); + DriveService.save( + this.state.element, + this.props.driveCollectionKey || this.driveCollectionKey, + ); + }} + /> +
+ ), + }, + ], + }, + ); + } + + if (this.props.attachmentMenu) { + this.common_menu.push(this.props.attachment_menu); + } + + this.common_menu.push({ type: 'separator' }); + + this.common_menu.push({ + type: 'menu', + text: Languages.t( + 'scenes.apps.drive.right_preview.operations_delete', + [], + 'Mettre à la corbeille', + ), + className: 'error', + onClick: () => { + DriveService.remove( + [this.props.data], + this.props.driveCollectionKey || this.driveCollectionKey, + ); + }, + }); + } else { + this.common_menu.push({ + type: 'menu', + text: Languages.t( + 'scenes.apps.drive.right_preview.operations_restore', + [], + 'Restaurer', + ), + onClick: () => { + DriveService.restore( + [this.props.data], + this.props.driveCollectionKey || this.driveCollectionKey, + ); + }, + }); + this.common_menu.push({ + type: 'menu', + text: Languages.t( + 'scenes.apps.drive.remove_definitely_menu', + [], + 'Supprimer définitivement', + ), + className: 'error', + onClick: () => { + AlertManager.confirm(() => { + DriveService.removeDefinitively( + [this.props.data], + this.props.driveCollectionKey || this.driveCollectionKey, + ); + }); + }, + }); + } + } + + if (this.props.additionalMenu && this.props.additionalMenu.length > 0) { + this.common_menu.push({ type: 'separator' }); + this.common_menu = this.common_menu.concat(this.props.additionalMenu); + } + } + } +} diff --git a/twake/frontend/src/app/components/drive/drive-multi-selector.js b/twake/frontend/src/app/components/drive/drive-multi-selector.js new file mode 100755 index 0000000000..c59290ede9 --- /dev/null +++ b/twake/frontend/src/app/components/drive/drive-multi-selector.js @@ -0,0 +1,276 @@ +import React, { Component } from 'react'; + +import './drive-multi-selector.scss'; +import SelectionsManager from 'app/deprecated/SelectionsManager/SelectionsManager.js'; +import './drive.scss'; + +export default class DriveMultiSelector extends React.Component { + constructor(props) { + super(); + this.state = { + start_drag: false, + dragging: true, + }; + this.move = this.move.bind(this); + this.end = this.end.bind(this); + this.start = this.start.bind(this); + this.pause = this.pause.bind(this); + this.unpause = this.unpause.bind(this); + + this.currentSelection = {}; + this.currentSelectionCount = 0; + + this.noMovementRefreshAnyway = setTimeout(''); + } + componentDidMount() { + this.scroller_container = this.props.scroller; + } + componentWillUnmount() { + clearInterval(this.noMovementRefreshAnyway); + + this.container.removeEventListener('mouseleave', this.pause); + this.container.removeEventListener('mouseenter', this.unpause); + document.removeEventListener('mousemove', this.move); + document.removeEventListener('mouseup', this.end); + document.body.classList.remove('no_select'); + } + pause() { + clearInterval(this.noMovementRefreshAnyway); + + this.setState({ dragging: false }); + } + unpause() { + this.setState({ dragging: true }); + } + end(evt) { + clearInterval(this.noMovementRefreshAnyway); + + this.setState({ start_drag: false }); + + document.removeEventListener('mousemove', this.move); + document.removeEventListener('mouseup', this.end); + this.container.removeEventListener('mouseleave', this.pause); + this.container.removeEventListener('mouseenter', this.unpause); + + document.body.classList.remove('no_select'); + + if (!this.did_drag) { + if (!evt.shiftKey && !this.did_start_drag == 0) { + SelectionsManager.unselectAll(); + } + this.did_start_drag = false; + return; + } + this.did_drag = false; + + Object.keys(this.currentSelection).forEach(id => { + if (this.currentSelection[id]) { + SelectionsManager.select(id); + } else { + SelectionsManager.unselect(id); + } + }); + this.did_start_drag = false; + + this.noMovementRefreshAnyway = setTimeout(() => { + this.state.left = 0; + this.state.right = 0; + this.state.width = 0; + this.state.height = 0; + this.setState({}); + }, 500); + } + start(evt) { + this.did_drag = false; + this.did_start_drag = true; + + this.element_position_cache = {}; + + SelectionsManager.setType(this.props.selectionType); + + clearInterval(this.noMovementRefreshAnyway); + this.currentSelection = {}; + + this.state.start_drag = true; + this.state.dragging = true; + var rect = window.getBoundingClientRect(this.container); + rect.x = rect.x || rect.left; + rect.y = rect.y || rect.top; + + this.drag_add = evt.nativeEvent.shiftKey; + this.drag_start = [ + evt.clientX - rect.left, + evt.clientY - rect.top, + this.container.scrollLeft, + this.container.scrollTop, + ]; + + document.addEventListener('mousemove', this.move); + document.addEventListener('mouseup', this.end); + this.container.addEventListener('mouseleave', this.pause); + this.container.addEventListener('mouseenter', this.unpause); + + document.body.classList.add('no_select'); + + var rect = {}; + rect.width = 0; + rect.height = 0; + rect.left = evt.clientX; + rect.top = evt.clientY; + this.autoSelect(rect); + } + move(evt) { + clearInterval(this.noMovementRefreshAnyway); + var rect = window.getBoundingClientRect(this.container); + rect.x = rect.x || rect.left; + rect.y = rect.y || rect.top; + + if (this.state.start_drag && this.state.dragging) { + this.did_drag = true; + + var pos = [evt.clientX - rect.left, evt.clientY - rect.top]; + + pos[0] = Math.min(pos[0], rect.width - 5); + pos[0] = Math.max(pos[0], 5); + + pos[1] = Math.min(pos[1], rect.height - 5); + pos[1] = Math.max(pos[1], 5); + + var w = this.drag_start[0] + this.drag_start[2] - (pos[0] + this.container.scrollLeft); + var h = this.drag_start[1] + this.drag_start[3] - (pos[1] + this.container.scrollTop); + var winv = w > 0; + var hinv = h > 0; + var selectorRect = { + width: Math.abs(w), + height: Math.abs(h), + left: this.drag_start[0] + this.drag_start[2] - Math.abs(winv ? w : 0), + top: this.drag_start[1] + this.drag_start[3] - Math.abs(hinv ? h : 0), + }; + this.setState(selectorRect); + + var rect = window.getBoundingClientRect(this.selector); + rect.x = rect.x || rect.left; + rect.y = rect.y || rect.top; + this.autoSelect(rect); + } + + var pos = [evt.clientX, evt.clientY]; + + if ( + rect.height + rect.top < pos[1] || + rect.top > pos[1] || + rect.width + rect.left < pos[0] || + rect.left > pos[0] + ) { + var newScrollTop = + this.container.scrollTop + + (pos[1] - ((pos[1] > rect.height + rect.top ? rect.height : 0) + rect.top)) / 10; + var newScrollLeft = + this.container.scrollLeft + + (pos[0] - ((pos[0] > rect.width + rect.top ? rect.width : 0) + rect.left)) / 10; + + if (this.container.scrollTop != newScrollTop || this.container.scrollLeft != newScrollLeft) { + this.container.scrollTop = newScrollTop; + this.container.scrollLeft = newScrollLeft; + this.state.dragging = true; + + this.noMovementRefreshAnyway = setTimeout(() => { + this.move({ + clientX: evt.clientX, + clientY: evt.clientY, + }); + }, 50); + } else { + this.state.dragging = false; + } + } + } + autoSelect(rect) { + this.currentSelectionCount = 0; + var scroll_top = this.container.scrollTop; + if (this.old_scroll_top != scroll_top) { + this.element_position_cache = {}; + } + this.old_scroll_top = scroll_top; + + Array.from(this.container.getElementsByClassName('js-drive-multi-selector-selectable')).forEach( + element => { + var element_id = element.getAttribute('drive_selector_unid'); + + var selected = SelectionsManager.selected_per_type[this.props.selectionType][element_id]; + var current_selection = this.currentSelection[element_id]; + + var over = false; + var elementRect = {}; + + if (this.element_position_cache[element_id]) { + elementRect = JSON.parse(JSON.stringify(this.element_position_cache[element_id])); + } else { + var er = window.getBoundingClientRect(element); + er.x = er.x || er.left; + er.y = er.y || er.top; + elementRect = JSON.parse(JSON.stringify(er)); + this.element_position_cache[element_id] = elementRect; + } + + if ( + !( + rect.left > elementRect.left + elementRect.width || + elementRect.left > rect.left + rect.width || + rect.top > elementRect.top + elementRect.height || + elementRect.top > rect.top + rect.height + ) + ) { + over = true; + } + + if ( + (over && this.drag_add && selected) || + (!over && this.drag_add && !selected) || + (!over && !this.drag_add) + ) { + element.dispatchEvent(new Event('drive_selector_out')); + this.currentSelection[element_id] = false; + } + if ( + (over && this.drag_add && !selected) || + (over && !this.drag_add) || + (!over && this.drag_add && selected) + ) { + element.dispatchEvent(new Event('drive_selector_over')); + this.currentSelection[element_id] = true; + this.currentSelectionCount++; + } + }, + ); + } + render() { + return ( +
{ + this.start(evt); + }} + onMouseUp={evt => { + this.end(evt); + }} + ref={node => (this.container = node)} + style={this.props.style || {}} + className={'drive_multiselector'} + > +
(this.selector = node)} + className={ + 'selectionRect ' + (this.state.start_drag && this.state.dragging ? 'visible ' : '') + } + style={{ + width: this.state.width, + height: this.state.height, + left: this.state.left, + top: this.state.top, + }} + /> + {this.props.children} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/Drive/DriveMultiSelector.scss b/twake/frontend/src/app/components/drive/drive-multi-selector.scss similarity index 100% rename from twake/frontend/src/app/components/Drive/DriveMultiSelector.scss rename to twake/frontend/src/app/components/drive/drive-multi-selector.scss diff --git a/twake/frontend/src/app/components/drive/drive.scss b/twake/frontend/src/app/components/drive/drive.scss new file mode 100755 index 0000000000..433aef9adb --- /dev/null +++ b/twake/frontend/src/app/components/drive/drive.scss @@ -0,0 +1,522 @@ +/* Drive */ + +.directory, +.file { + .file_loader { + width: 32px; + height: 32px; + display: inline-block; + margin: auto; + } + .options { + padding-left: 5px; + display: none; + } + + &:hover { + .options { + display: block; + } + } +} + +.directory_drop_zone { + display: inline-block; +} +.directory { + background: #fff; + border: 1px solid var(--grey-background); + height: 50px; + box-sizing: border-box; + display: inline-flex; + flex-direction: row; + line-height: 32px; + margin-right: 16px; + margin-bottom: 16px; + border-radius: var(--border-radius-base); + font-size: 13px; + vertical-align: middle; + width: 200px; + padding: 8px; + font-weight: 500; + padding-right: 12px; + cursor: pointer; + + .text { + font-size: 12px; + font-weight: bold; + } + + &:hover:not(.notInDrive) { + box-shadow: 4px 4px 16px 0 #00000022; + border-color: #fff; + } + + .options { + .m-icon-small { + font-size: 20px !important; + } + } + + .app_icon { + width: 20px; + background-size: contain; + background-position: center; + background-repeat: no-repeat; + height: 20px; + margin-top: 2px; + } + + .icon { + font-size: 14px; + padding-right: 8px; + margin-left: 6px; + padding-top: 4px; + + .m-icon-small { + color: var(--warning); + font-size: 20px !important; + } + + i.icon-fontastic { + position: relative; + top: 8px; + } + + .icon { + height: 30px; + background-size: 16px auto; + background-position: center left; + background-repeat: no-repeat; + } + } +} + +.file { + overflow: hidden; + border: 1px solid var(--grey-background); + background: #fff; + height: 180px; + width: 216px; + box-sizing: border-box; + display: inline-flex; + flex-direction: column; + line-height: 30px; + margin-right: 16px; + margin-bottom: 16px; + border-radius: var(--border-radius-base); + font-size: 13px; + vertical-align: middle; + position: relative; + cursor: pointer; + + &:hover:not(.notInDrive) { + box-shadow: 4px 4px 16px 0 #00000022; + border-color: #fff; + } + + .options { + .m-icon-small { + font-size: 20px !important; + } + } + + &.mini { + height: 32px; + + .data { + border-top: none; + .no-grid { + display: none; + } + } + + .preview { + height: 32px; + background: #fff !important; + + &:after { + content: none; + } + } + } + + .preview { + width: 216px; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + background-color: #f5f5f7; + flex: 1; + + .tags_list { + position: absolute; + top: 4px; + padding-left: 8px; + line-height: 30px; + } + + &.no_preview { + background-color: #f5f5f7; + background-repeat: no-repeat; + background-size: 64px; + } + + /*&:after { + content: ""; + position: absolute; + width: 100%; + height: 100%; + background: linear-gradient(180deg, rgba(0,0,0,0) 40%, rgba(0,0,0,0.05) 70%, rgba(0,0,0,0.5) 100%); + }*/ + } + + .data { + display: flex; + flex-direction: row; + padding-left: 8px; + padding-right: 8px; + bottom: 0px; + color: var(--black); + height: 32px; + font-weight: 500; + width: 100%; + box-sizing: border-box; + border-top: 1px solid var(--grey-background); + + .icon { + height: 20px; + width: 20px; + box-sizing: border-box; + border-radius: var(--border-radius-base); + margin-right: 6px; + margin-left: -3px; + margin-top: 5px; + color: #fff; + text-align: center; + background-size: 70%; + background-repeat: no-repeat; + background-position: center; + + i.icon-fontastic { + position: relative; + top: 4px; + } + } + } +} + +.draggable_clone { + .file, + .directory { + opacity: 1; + box-shadow: 4px 4px 16px 0 #00000022; + border-color: #fff; + } +} + +.dragging.drag_file .drive_multiselector { + .file.is_selected, + .directory.is_selected { + opacity: 0; + transition: opacity 0.2s; + } +} + +.file, +.directory { + transition: opacity 0s; + + &.notInDrive { + margin-bottom: 0px; + } + + &.dragging_opacity { + opacity: 0; + } + + &.is_selected { + background: var(--primary); + color: #fff; + box-shadow: none; + + .file_type_icon svg, + .file_type_icon svg * { + fill: #fff; + } + + &:hover:not(.notInDrive), + .data { + background-color: var(--primary); + color: #fff; + } + } + + .text { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .created-by, + .last-modified { + width: 200px; + } + + .size { + text-align: right; + width: 70px; + } + + .last-modified { + text-align: right; + width: 120px; + } + + .detail_preview_parent { + width: 32px; + margin-left: 12px; + + .detail_preview { + width: 32px; + height: 32px; + border-radius: var(--border-radius-base); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-color: var(--primary-background); + + &.no_preview { + background-size: 60%; + } + } + } +} + +.drive_view.list { + .directory_drop_zone { + display: inherit; + } +} + +.drive_view.list .directory, +.drive_view.list .file { + margin-right: 0px; + margin-bottom: 0px; + border: 0; + border-bottom: 1px solid var(--grey-background); + border-top: 1px solid var(--grey-background); + border-radius: 2px; + width: 100%; + height: 64px; + padding-top: 16px; + color: var(--black); + margin-top: -1px; + padding-right: 12px; + + &.exit-active, + &.enter-active { + margin-top: -1px !important; + } + + .data { + border-top: 0px; + bottom: -1px; + } + + .text { + font-size: 14px; + } + + .options { + display: block; + } + + &:hover:not(.notInDrive):not(.is_selected) { + box-shadow: none; + background: var(--primary-background); + } + + &.is_selected { + background: var(--primary); + color: #fff; + box-shadow: none; + } +} + +.drive_view.list .file .preview { + display: none; +} + +.drive_view.list { + .rounded-btn { + margin-top: 10px; + } +} + +.drive_view.grid { + .is_selected.file { + background: var(--primary); + color: #fff; + box-shadow: none; + } +} + +.drive_view.grid .no-grid { + display: none; +} +.drive_view.list .no-list { + display: none; +} + +.file_type_icon { + line-height: 38px; + width: 24px; + + svg, + svg * { + fill: var(--primary); + } + + &.link { + background-image: url('./icons/link.svg'); + } + + &.code { + background-image: url('./icons/code.svg'); + } + + &.document { + background-image: url('./icons/document.svg'); + } + + &.image { + background-image: url('./icons/image.svg'); + } + + &.pdf { + background-image: url('./icons/pdf.svg'); + } + + &.slides { + background-image: url('./icons/slides.svg'); + } + + &.sound, &.audio { + background-image: url('./icons/sound.svg'); + } + + &.spreadsheet { + background-image: url('./icons/spreadsheet.svg'); + } + + &.svg { + background-image: url('./icons/svg.svg'); + } + + &.video { + background-image: url('./icons/video.svg'); + } + + &.archive { + background-image: url('./icons/archive.svg'); + } + + &.other { + background-image: url('./icons/file.svg'); + } +} + +.drive_view.list .file_type_icon { + line-height: 38px; + width: 34px; + text-align: center; +} + +/* version details */ +.versionDetails { + min-height: 250px; + + .text.no-more { + text-align: center; + width: 100%; + opacity: 0.5; + margin-top: 32px; + margin-bottom: 32px; + } + + .version { + display: flex; + padding: 24px 0px; + border-bottom: solid 1px var(--grey-background); + .titleVersionDetails { + font-size: 24px; + color: var(--black); + font-weight: bold; + margin-bottom: 24px; + } + .info { + flex: 0.5; + margin-bottom: 8px; + .versionTitle { + font-size: 14px; + font-weight: bold; + color: var(--black); + } + .versionDate { + font-size: 14px; + color: var(--black); + } + } + .name { + flex: 0.5; + font-size: 14px; + line-height: 24px; + color: var(--black); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .more { + } + } +} +.footerVersionDetails { + display: flex; + .addVersion { + flex: 1; + .addVersionButton { + width: 100%; + height: 24px; + line-height: 24px; + } + .addVersionButton:hover { + cursor: pointer; + opacity: 0.8; + } + .icon { + display: inline-block; + width: 24px; + height: 24px; + .iconWithBackground { + width: 24px; + height: 24px; + display: inline-block; + background-color: var(--grey-background); + border-radius: var(--border-radius-base); + } + } + .footerTitle { + margin-left: 8px; + display: inline-block; + font-size: 14px; + font-weight: bold; + color: var(--black); + .addVersionButton:hover { + cursor: pointer; + opacity: 0.8; + } + } + } +} diff --git a/twake/frontend/src/app/components/drive/file-picker/file-picker.js b/twake/frontend/src/app/components/drive/file-picker/file-picker.js new file mode 100755 index 0000000000..c503d6e789 --- /dev/null +++ b/twake/frontend/src/app/components/drive/file-picker/file-picker.js @@ -0,0 +1,212 @@ +import React, { Component } from 'react'; + +import DriveService from 'app/deprecated/Apps/Drive/Drive.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Languages from 'app/features/global/services/languages-service'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import UIFile from '../ui/file.js'; +import UIDirectory from '../ui/directory.js'; +import LeftIcon from '@material-ui/icons/KeyboardArrowLeftOutlined'; +import NewFolderIcon from '@material-ui/icons/CreateNewFolderOutlined'; +import Menu from 'components/menus/menu.js'; +import Button from 'components/buttons/button.js'; +import Input from 'components/inputs/input.js'; +import './file-picker.scss'; + +export default class FilePicker extends React.Component { + constructor(props) { + super(); + this.drive_channel = 'file_picker_' + Workspaces.currentWorkspaceId; + this.drive_collection_key = this.drive_channel; + + this.state = { + i18n: Languages, + drive_repository: Collections.get('drive'), + app_drive_service: DriveService, + current_selection: {}, + creating_folder: false, + }; + + Languages.addListener(this); + Collections.get('drive').addListener(this); + DriveService.addListener(this); + } + componentWillUnmount() { + Languages.removeListener(this); + Collections.get('drive').removeListener(this); + DriveService.removeListener(this); + + if (this.drive_channel) { + Collections.get('drive').removeSource( + this.state.app_drive_service.current_collection_key_channels[this.drive_channel], + ); + } + } + componentDidMount() { + this.changeCurrentDirectory({ id: (this.props.initialDirectory || {}).id || '' }); + } + clickOnFile(file) { + if (this.props.mode == 'select_file') { + this.setState({ current_selection: file }); + } + } + changeCurrentDirectory(directory) { + if (this.props.mode == 'select_file') { + this.setState({ current_selection: {} }); + } + if (this.props.mode == 'select_location') { + this.setState({ current_selection: directory }); + } + DriveService.changeCurrentDirectory(this.drive_channel, directory); + } + submit() { + var result = null; + if (this.props.mode == 'select_file') { + result = this.state.current_selection; + } + if (this.props.mode == 'select_location') { + result = this.state.app_drive_service.current_directory_channels[this.drive_channel] || {}; + } + Menu.closeAll(); + if (this.props.onChoose) this.props.onChoose(result); + } + render() { + var workspace_id = Workspaces.currentWorkspaceId; + var directory = + this.state.app_drive_service.current_directory_channels[this.drive_channel] || {}; + var directory_id = directory.id; + + var filter_dir = { + workspace_id: workspace_id, + parent_id: directory_id, + is_directory: true, + trash: false, + }; + var directories = this.state.drive_repository + .findBy(filter_dir) + .sort((a, b) => (a.name || '').localeCompare(b.name || '')); + + var filter_files = { + workspace_id: workspace_id, + parent_id: directory_id, + is_directory: false, + trash: false, + }; + var files = this.state.drive_repository + .findBy(filter_files) + .sort((a, b) => (a.name || '').localeCompare(b.name || '')); + + var allow_go_parent = true; + var drive_channel = null; + if (!drive_channel && (this.props.initialDirectory || {}).id == directory_id) { + allow_go_parent = false; + } + + return ( +
+
+ {directory.parent_id && allow_go_parent && ( + { + this.changeCurrentDirectory({ id: directory.parent_id }); + }} + /> + )}{' '} + {directory.parent_id + ? directory.name + : Languages.t('app.identity?.name.twake_drive', [], 'Documents')} +
+
+ {directories.map((item, index) => ( +
DriveService.changeCurrentDirectory(this.drive_channel, item)} + > + +
+ ))} + {files.map((item, index) => ( +
this.clickOnFile(item)} + > + +
+ ))} +
+ + {this.state.creating_folder && ( +
+ + (node ? node.focus() : '')} + type="text" + defaultValue={''} + placeholder={Languages.t( + 'scenes.apps.drive.navigators.navigator_content.directory_name', + [], + 'Nom du dossier', + )} + onKeyPress={e => { + if (e.key === 'Enter') { + DriveService.createDirectory( + directory.workspace_id, + e.target.value, + directory, + DriveService.current_collection_key_channels[this.drive_channel], + res => { + this.changeCurrentDirectory(res); + }, + ); + this.setState({ creating_folder: false }); + } + }} + /> +
+ )} + {!this.state.creating_folder && ( +
+ {!this.state.creating_folder && directory.workspace_id && ( + + )} + {this.props.mode == 'select_location' && ( +
+ )} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/Drive/FilePicker/FilePicker.scss b/twake/frontend/src/app/components/drive/file-picker/file-picker.scss similarity index 100% rename from twake/frontend/src/app/components/Drive/FilePicker/FilePicker.scss rename to twake/frontend/src/app/components/drive/file-picker/file-picker.scss diff --git a/twake/frontend/src/app/components/drive/file.tsx b/twake/frontend/src/app/components/drive/file.tsx new file mode 100755 index 0000000000..24d5a3516b --- /dev/null +++ b/twake/frontend/src/app/components/drive/file.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import Draggable from 'components/draggable/draggable'; +import DriveElement from './drive-element.js'; +import './drive.scss'; +import UIFile from './ui/file.js'; +import Loader from 'components/loader/loader.js'; +import WorkspaceUserRights from 'app/features/workspaces/services/workspace-user-rights-service'; +import Languages from 'app/features/global/services/languages-service'; + +type PropsType = { [key: string]: any }; + +type StateType = any; + +type NodeType = any; + +export default class File extends DriveElement { + node: NodeType; + state: StateType; + constructor() { + super(); + this.state = { + loading: true, + }; + } + componentDidMount() { + super.componentDidMount(); + if (this.state.loading) { + setTimeout(() => { + this.setState({ loading: false }); + }, 4000); + } + } + render() { + if (!this.state.element || !this.state.element.front_id) { + return ( +
+ {this.state.loading && } + {!this.state.loading && ( + + {Languages.t('scenes.apps.drive.preview_bloc.error_file', [], 'File not found.')} + + )} +
+ ); + } else { + this.state.loading = false; + } + + if (this.props.hide) { + return ''; + } + + const mini = (!this.state.element.has_preview && this.props.notInDrive) || this.props.mini; + return ( + (this.node = node)} + onClick={(evt: any) => this.clickElement(evt, this.props.previewonly)} + onDoubleClick={this.props.onDoubleClick} + parentClassOnDrag="drive_view list" + onDragStart={(evt: any) => { + this.dragElement(evt); + }} + minMove={10} + data={{ type: 'file', selection_type: this.props.selectionType, data: this.props.data }} + deactivated={WorkspaceUserRights.isNotConnected() || this.props.notInDrive} + > + { + e.preventDefault(); + e.stopPropagation(); + this.props.removeOnClick(); + }} + /> + + ); + } +} diff --git a/twake/frontend/src/app/components/Drive/Icons/archive.js b/twake/frontend/src/app/components/drive/icons/archive.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/archive.js rename to twake/frontend/src/app/components/drive/icons/archive.js diff --git a/twake/frontend/src/app/components/Drive/Icons/archive.svg b/twake/frontend/src/app/components/drive/icons/archive.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/archive.svg rename to twake/frontend/src/app/components/drive/icons/archive.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/code.js b/twake/frontend/src/app/components/drive/icons/code.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/code.js rename to twake/frontend/src/app/components/drive/icons/code.js diff --git a/twake/frontend/src/app/components/Drive/Icons/code.svg b/twake/frontend/src/app/components/drive/icons/code.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/code.svg rename to twake/frontend/src/app/components/drive/icons/code.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/document.js b/twake/frontend/src/app/components/drive/icons/document.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/document.js rename to twake/frontend/src/app/components/drive/icons/document.js diff --git a/twake/frontend/src/app/components/Drive/Icons/document.svg b/twake/frontend/src/app/components/drive/icons/document.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/document.svg rename to twake/frontend/src/app/components/drive/icons/document.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/file.js b/twake/frontend/src/app/components/drive/icons/file.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/file.js rename to twake/frontend/src/app/components/drive/icons/file.js diff --git a/twake/frontend/src/app/components/Drive/Icons/file.svg b/twake/frontend/src/app/components/drive/icons/file.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/file.svg rename to twake/frontend/src/app/components/drive/icons/file.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/image.js b/twake/frontend/src/app/components/drive/icons/image.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/image.js rename to twake/frontend/src/app/components/drive/icons/image.js diff --git a/twake/frontend/src/app/components/Drive/Icons/image.svg b/twake/frontend/src/app/components/drive/icons/image.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/image.svg rename to twake/frontend/src/app/components/drive/icons/image.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/link.js b/twake/frontend/src/app/components/drive/icons/link.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/link.js rename to twake/frontend/src/app/components/drive/icons/link.js diff --git a/twake/frontend/src/app/components/Drive/Icons/link.svg b/twake/frontend/src/app/components/drive/icons/link.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/link.svg rename to twake/frontend/src/app/components/drive/icons/link.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/pdf.js b/twake/frontend/src/app/components/drive/icons/pdf.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/pdf.js rename to twake/frontend/src/app/components/drive/icons/pdf.js diff --git a/twake/frontend/src/app/components/Drive/Icons/pdf.svg b/twake/frontend/src/app/components/drive/icons/pdf.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/pdf.svg rename to twake/frontend/src/app/components/drive/icons/pdf.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/slides.js b/twake/frontend/src/app/components/drive/icons/slides.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/slides.js rename to twake/frontend/src/app/components/drive/icons/slides.js diff --git a/twake/frontend/src/app/components/Drive/Icons/slides.svg b/twake/frontend/src/app/components/drive/icons/slides.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/slides.svg rename to twake/frontend/src/app/components/drive/icons/slides.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/sound.js b/twake/frontend/src/app/components/drive/icons/sound.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/sound.js rename to twake/frontend/src/app/components/drive/icons/sound.js diff --git a/twake/frontend/src/app/components/Drive/Icons/sound.svg b/twake/frontend/src/app/components/drive/icons/sound.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/sound.svg rename to twake/frontend/src/app/components/drive/icons/sound.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/spreadsheet.js b/twake/frontend/src/app/components/drive/icons/spreadsheet.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/spreadsheet.js rename to twake/frontend/src/app/components/drive/icons/spreadsheet.js diff --git a/twake/frontend/src/app/components/Drive/Icons/spreadsheet.svg b/twake/frontend/src/app/components/drive/icons/spreadsheet.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/spreadsheet.svg rename to twake/frontend/src/app/components/drive/icons/spreadsheet.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/svg.js b/twake/frontend/src/app/components/drive/icons/svg.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/svg.js rename to twake/frontend/src/app/components/drive/icons/svg.js diff --git a/twake/frontend/src/app/components/Drive/Icons/svg.svg b/twake/frontend/src/app/components/drive/icons/svg.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/svg.svg rename to twake/frontend/src/app/components/drive/icons/svg.svg diff --git a/twake/frontend/src/app/components/Drive/Icons/video.js b/twake/frontend/src/app/components/drive/icons/video.js similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/video.js rename to twake/frontend/src/app/components/drive/icons/video.js diff --git a/twake/frontend/src/app/components/Drive/Icons/video.svg b/twake/frontend/src/app/components/drive/icons/video.svg similarity index 100% rename from twake/frontend/src/app/components/Drive/Icons/video.svg rename to twake/frontend/src/app/components/drive/icons/video.svg diff --git a/twake/frontend/src/app/components/drive/ui/directory.js b/twake/frontend/src/app/components/drive/ui/directory.js new file mode 100755 index 0000000000..f6e729c1a2 --- /dev/null +++ b/twake/frontend/src/app/components/drive/ui/directory.js @@ -0,0 +1,54 @@ +import React from 'react'; + +import Icon from 'components/icon/icon.js'; +import FolderIcon from '@material-ui/icons/FolderOutlined'; +import Menu from 'components/menus/menu.js'; +import Numbers from 'app/features/global/utils/Numbers'; +import '../drive.scss'; +import 'moment-timezone'; +import { getCompanyApplication as getApplication } from 'app/features/applications/state/company-applications'; + +export default class Directory extends React.Component { + constructor(props) { + super(); + } + render() { + var app = {}; + if (this.props.data.application_id && this.props.data.external_storage) { + app = getApplication(this.props.data.application_id); + } + + return [ +
+
+ {!app.id && } + {!!app.id && ( +
+ )} +
+
+ {this.props.data.name} + {!!app.id && ({app.identity?.name})} +
+ + {(this.props.data.acces_info || {}).token && ( + + )} + + {this.props.details && ( +
+ {this.props.data.size ? Numbers.humanFileSize(this.props.data.size, true) : '-'} +
+ )} + {this.props.menu && this.props.menu.length > 0 && ( + + + + )} +
, + ]; + } +} diff --git a/twake/frontend/src/app/components/drive/ui/file-type.js b/twake/frontend/src/app/components/drive/ui/file-type.js new file mode 100755 index 0000000000..acc76f8cab --- /dev/null +++ b/twake/frontend/src/app/components/drive/ui/file-type.js @@ -0,0 +1,62 @@ +import React, { Component } from 'react'; + +import Archive from '../icons/archive.js'; +import Code from '../icons/code.js'; +import Document from '../icons/document.js'; +import Files from '../icons/file.js'; +import Images from '../icons/image.js'; +import Link from '../icons/link.js'; +import Pdf from '../icons/pdf.js'; +import Slide from '../icons/slides.js'; +import Sound from '../icons/sound.js'; +import Spreadsheet from '../icons/spreadsheet.js'; +import Svg from '../icons/svg.js'; +import Video from '../icons/video.js'; + +export default class FileType extends React.Component { + /* props : type (string) */ + constructor(props) { + super(); + } + render() { + var type = this.props.type; + var TypeIcon = Files; + switch (type) { + case 'link': + TypeIcon = Link; + break; + case 'code': + TypeIcon = Code; + break; + case 'document': + TypeIcon = Document; + break; + case 'image': + TypeIcon = Images; + break; + case 'pdf': + TypeIcon = Pdf; + break; + case 'slides': + TypeIcon = Slide; + break; + case 'audio': + TypeIcon = Sound; + break; + case 'spreadsheet': + TypeIcon = Spreadsheet; + break; + case 'svg': + TypeIcon = Svg; + break; + case 'video': + TypeIcon = Video; + break; + case 'archive': + TypeIcon = Archive; + break; + default: + } + return ; + } +} diff --git a/twake/frontend/src/app/components/drive/ui/file.js b/twake/frontend/src/app/components/drive/ui/file.js new file mode 100755 index 0000000000..7d6c35c372 --- /dev/null +++ b/twake/frontend/src/app/components/drive/ui/file.js @@ -0,0 +1,118 @@ +import React from 'react'; +import moment from 'moment'; +import 'moment-timezone'; + +import Icon from 'components/icon/icon'; +import Menu from 'components/menus/menu'; +import DriveService from 'app/deprecated/Apps/Drive/Drive'; +import Numbers from 'app/features/global/utils/Numbers'; +import FileType from './file-type'; +import TagPicker from 'components/tag-picker/tag-picker'; +import { addApiUrlIfNeeded } from 'app/features/global/utils/URLUtils'; +import '../drive.scss'; +import { formatTime } from '@features/global/utils/Numbers'; + +export default class File extends React.Component { + constructor(props) { + super(); + } + render() { + var mini = this.props.mini; + + var date = false; + if (this.props.data.modified) { + date = new Date(this.props.data.modified * 1000); + } + if (this.props.data.added && this.props.isVersion) { + date = new Date(this.props.data.added * 1000); + } + + var date_string = date ? formatTime(date) : '-'; + + return [ +
+
+ +
+
, +
+
+ +
+
+ {!!this.props.versionLabel &&
{this.props.versionLabel}
} + {this.props.data.name} + {!this.props.isVersion && (this.props.data.versions || {}).length > 1 && ( + + ({(this.props.data.versions || {}).length} versions) + + )} +    + +
+ + {(this.props.data.acces_info || {}).token && ( + + )} + {this.props.data.url && } + + {/* +
+ {this.state.element.created_by || "-"} +
+ */} + {this.props.details && [ +
{date_string}
, +
+ {this.props.data.size ? Numbers.humanFileSize(this.props.data.size, true) : '-'} +
, + ]} + {!this.props.isVersion && ( +
+
+
+ )} + {this.props.menu && this.props.menu.length > 0 && ( + + + + )} + + {this.props.removeIcon === true && ( + + )} +
, + ]; + } +} diff --git a/twake/frontend/src/app/components/drive/version-details.js b/twake/frontend/src/app/components/drive/version-details.js new file mode 100755 index 0000000000..af5c8ca829 --- /dev/null +++ b/twake/frontend/src/app/components/drive/version-details.js @@ -0,0 +1,128 @@ +import React from 'react'; +import Languages from 'app/features/global/services/languages-service'; +import Icon from 'components/icon/icon.js'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import DriveService from 'app/deprecated/Apps/Drive/Drive.js'; +import UploadZone from 'components/uploads/upload-zone'; +import WorkspaceUserRights from 'app/features/workspaces/services/workspace-user-rights-service'; +import MediumPopupManager from 'app/components/modal/modal-manager'; +import { ObjectModal, ObjectModalTitle } from 'components/object-modal/deprecated-object-modal.js'; +import UIFile from './ui/file.js'; +import 'moment-timezone'; + +import './drive.scss'; + +export default class VersionDetails extends React.Component { + constructor() { + super(); + this.state = { + workspaces: Workspaces, + i18n: Languages, + }; + Languages.addListener(this); + DriveService.addListener(this); + Collections.get('drive').addListener(this); + } + componentWillUnmount() { + Languages.removeListener(this); + DriveService.removeListener(this); + Collections.get('drive').removeListener(this); + } + render() { + var countVersion = (this.props.file.versions || []).length; + return ( + MediumPopupManager.closeAll()} + footer={ +
+
+
{ + if (this.upload_zone) { + this.upload_zone.open(); + } + }} + > +
+ +
+
+ {Languages.t('components.drive.new_versions', [], 'Ajouter une nouvelle version')} +
+
+
+
+ } + title={ +
+ + {Languages.t('scenes.apps.drive.right_preview.versions', [], 'Versions')} + +
+ } + > +
+ (this.upload_zone = node)} + driveCollectionKey={''} + parent={this.props.file.parent_id} + driveCollectionKey={{ id: this.props.file.parent_id }} + uploadOptions={{ + workspace_id: this.state.workspaces.currentWorkspaceId, + new_version: true, + file_id: this.props.file.id, + }} + allowPaste={true} + > + {(this.props.file.versions || []) + .sort((a, b) => { + return b.added - a.added; + }) + .map((version, index) => { + var data = {}; + if (index > 0) { + data.extension = this.props.file.extension; + data.name = version.name; + data.creator = version.creator; + data.size = version.size; + } else { + data = JSON.parse(JSON.stringify(this.props.file)); + } + data.added = version.added; + return ( +
+ { + var link = DriveService.getLink(this.props.file, version.id, 1); + window.open(link); + }, + }, + ]} + details={true} + /> +
+ ); + })} +
+
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/editable-text/editable-text.js b/twake/frontend/src/app/components/editable-text/editable-text.js new file mode 100755 index 0000000000..1dd1482f30 --- /dev/null +++ b/twake/frontend/src/app/components/editable-text/editable-text.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; +import './editable-text.scss'; + +import Input from 'components/inputs/input.js'; + +export default class EditableText extends React.Component { + constructor(props) { + super(); + this.props = props; + + this.state = { + value: '#FF0000', + }; + } + render() { + return ( +
+ this.setState({ value: evt.target.value })} + /> +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/EditableText/EditableText.scss b/twake/frontend/src/app/components/editable-text/editable-text.scss similarity index 100% rename from twake/frontend/src/app/components/EditableText/EditableText.scss rename to twake/frontend/src/app/components/editable-text/editable-text.scss diff --git a/twake/frontend/src/app/components/emoji-picker/emoji-picker.js b/twake/frontend/src/app/components/emoji-picker/emoji-picker.js new file mode 100755 index 0000000000..d7ebd97ce0 --- /dev/null +++ b/twake/frontend/src/app/components/emoji-picker/emoji-picker.js @@ -0,0 +1,144 @@ +import React from 'react'; +import { Picker } from 'emoji-mart'; +import Emojione from 'components/emojione/emojione'; +import { getAsFrontUrl } from 'app/features/global/utils/URLUtils'; +import './emoji-picker.scss'; +import 'emoji-mart/css/emoji-mart.css'; +import Languages from 'app/features/global/services/languages-service'; +import { isArray } from 'lodash'; + +Picker.defaultProps.backgroundImageFn = function backgroundImageFn(set, sheetSize) { + sheetSize = 20; + return getAsFrontUrl( + '/public/emoji-datasource/'.concat(set, '/sheets-256/').concat(sheetSize, '.png'), + ); +}; +export default class EmojiPicker extends React.Component { + /* + props = { + preferedEmoji : Array of emoji's shortname + onChange : called when a smiley is selected + } + */ + constructor(props) { + super(); + this.props = props; + this.state = { + suggestions: [], + currentTitle: '', + availableCategories: [], + scrollToRow: 0, + loaded: false, + }; + this.currentTitleIndex = 100000; + this.clickScrollToRow = 0; + } + componentWillUnmount() {} + onUpdate(item) {} + onRemove(item, ev) {} + onChange(list) { + if (list.length > 0) { + if (this.props.onChange) { + this.props.onChange(list[0]); + } + this.setState({ list: [] }); + } + } + renderItemChoosen(item) { + return ( +
+ +
+ ); + } + renderItem(item) { + return ( +
+ +
+ ); + } + scrollToCategory(category) { + var index = 0; + this.state.suggestions.forEach((item, i) => { + if (item.value == category) { + index = i; + return false; + } + }); + this.clickScrollToRow = index; + if (this.state.scrollToRow != index) { + this.setState({ scrollToRow: index }); + } else { + this.list_node.forceUpdateGrid(); + } + } + select(emoji) { + if (this.picker) { + this.picker.onSelect(emoji); + } else { + this.onChange([emoji]); + } + } + getPrefered() { + var pref = this.props.preferedEmoji || [ + ':thumbsup:', + ':thumbsdown:', + ':hearts:', + ':tada:', + ':smile:', + ':confused:', + ]; + if ( + typeof this.props.selected === 'string' && + this.props.selected && + pref.indexOf(this.props.selected) < 0 + ) { + pref.unshift(this.props.selected); + } + if (isArray(this.props.selected)) { + this.props.selected.forEach(s => pref.unshift(s)); + } + return pref; + } + componentDidMount() { + setTimeout(() => { + this.setState({ loaded: true }); + }, 300); + } + render() { + if (!this.state.loaded) { + return
; + } + return ( +
+ +
+ ); + } +} diff --git a/twake/frontend/src/app/components/EmojiPicker/EmojiPicker.scss b/twake/frontend/src/app/components/emoji-picker/emoji-picker.scss similarity index 100% rename from twake/frontend/src/app/components/EmojiPicker/EmojiPicker.scss rename to twake/frontend/src/app/components/emoji-picker/emoji-picker.scss diff --git a/twake/frontend/src/app/components/Emojione/Emojione.scss b/twake/frontend/src/app/components/emojione/emojione.scss similarity index 100% rename from twake/frontend/src/app/components/Emojione/Emojione.scss rename to twake/frontend/src/app/components/emojione/emojione.scss diff --git a/twake/frontend/src/app/components/emojione/emojione.tsx b/twake/frontend/src/app/components/emojione/emojione.tsx new file mode 100755 index 0000000000..49fccd7446 --- /dev/null +++ b/twake/frontend/src/app/components/emojione/emojione.tsx @@ -0,0 +1,112 @@ +//@ts-nocheck +//We need this because of a bug in emoji_mart fallback implementationimport React, { Component } from 'react'; + +import React, { Component } from 'react'; + +import 'emoji-mart/css/emoji-mart.css'; + +import { getEmojiDataFromNative, Emoji } from 'emoji-mart'; +import data from 'emoji-mart/data/all.json'; + +import emojione from 'emojione'; +import Icon from 'components/icon/icon.js'; + +import './emojione.scss'; +import { getAsFrontUrl } from 'app/features/global/utils/URLUtils'; + +type Props = { + type: string; + size?: number; + className?: string; + s64?: boolean; + s128?: boolean; + emoji?: string; +}; + +const type_to_uni: any = {}; + +const getFromEmojione = (props: Props) => { + //Use from local server + let html: string | '' = ''; + html = emojione.toImage(props.type || props.emoji || ''); + html = html?.replace('https://cdn.jsdelivr.net/emojione/assets/3.1/png/', '/public/emojione/'); + + if (props.s64) { + html = html?.replace('/32/', '/64/'); + } else if (props.s128) { + html = html?.replace('/32/', '/128/'); + } + return { __html: html }; +}; + +class EmojioneFallback extends Component { + // WIP + render() { + return ( + + ); + } +} + +const Emojione = React.memo((props: Props) => { + if (typeof props.type != 'string') { + return <>; + } + + if (props.type === 'trash') { + return ; + } + + if (props.type.substr(0, 7) === ':twake-') { + return ( + + ); + } + + if (props.type.substr(0, 7) === 'http://' || props.type.substr(0, 8) === 'https://') { + return ( + + ); + } + + let size = props.size || 16; + if (size > 32 || props.s64 || props.s128) { + return ; + } + + const uni = + type_to_uni[props.type] || + //@ts-ignore + getEmojiDataFromNative(emojione.shortnameToUnicode(props.type), 'apple', data); + type_to_uni[props.type] = uni; + + return ( + + { + if ([16, 20, 32, 64].indexOf(size) < 0) { + size = 64; + } + return getAsFrontUrl( + '/public/emoji-datasource/'.concat(set, '/sheets-256/').concat(size, '.png'), + ); + }} + emoji={uni || props.type} + set="apple" + size={size} + fallback={() => } + /> + + ); +}); + +export default Emojione; diff --git a/twake/frontend/src/app/components/file-uploads/pending-file-components/pending-file-row.tsx b/twake/frontend/src/app/components/file-uploads/pending-file-components/pending-file-row.tsx new file mode 100644 index 0000000000..8c747e2411 --- /dev/null +++ b/twake/frontend/src/app/components/file-uploads/pending-file-components/pending-file-row.tsx @@ -0,0 +1,195 @@ +import React from 'react'; +import { PauseCircle, PlayCircle, Trash2 } from 'react-feather'; +import { Row, Col, Typography, Divider, Progress, Button, Tooltip } from 'antd'; +import { capitalize } from 'lodash'; + +import { + isPendingFileStatusCancel, + isPendingFileStatusError, + isPendingFileStatusPause, + isPendingFileStatusPending, + isPendingFileStatusSuccess, +} from '../../../features/files/utils/pending-files'; +import Languages from 'app/features/global/services/languages-service'; +import { useUpload } from 'app/features/files/hooks/use-upload'; +import { PendingFileRecoilType, PendingFileType } from 'app/features/files/types/file'; + +import '../../file/file.scss'; + +type PropsType = { + pendingFileState: PendingFileRecoilType; + pendingFile: PendingFileType; +}; + +const { Text } = Typography; +export default ({ pendingFileState, pendingFile }: PropsType) => { + const { pauseOrResumeUpload, cancelUpload } = useUpload(); + + const getProgressStrokeColor = (status: PendingFileRecoilType['status']) => { + if (isPendingFileStatusCancel(status)) return 'var(--error)'; + if (isPendingFileStatusError(status)) return 'var(--error)'; + if (isPendingFileStatusPause(status)) return 'var(--warning)'; + if (isPendingFileStatusPending(status)) return 'var(--progress-bar-color)'; + + return 'var(--success)'; + }; + + const setStatus = () => { + switch (pendingFileState.status) { + case 'error': + case 'pause': + case 'cancel': + return 'exception'; + case 'pending': + return 'active'; + case 'success': + return 'success'; + default: + return 'normal'; + } + }; + + return ( +
+ + + {pendingFile.originalFile.name ? ( + + + {capitalize(pendingFile.originalFile.name)} + + {isPendingFileStatusPause(pendingFile.status) && ( + + {/* TODO Add translation here */} + (paused) + + )} + + ) : ( +
+ )} + + + + {pendingFileState.id ? ( + !isPendingFileStatusSuccess(pendingFileState.status) && + !isPendingFileStatusError(pendingFileState.status) ? ( + + +
+ )} +
+
(this.dom_fake_separator_top = node)} /> +
(this.dom_visualized_messages_top = node)} + > + {this.state.messages.map((message, _i) => { + if (this.compare(message, this.messages_med) <= 0) { + var tmp = previous_message; + previous_message = message; + var i = _i; + return ( +
+ (this.dom_messages[i] = { + node: node, + message: message, + scrollTop: (this.dom_messages[i] || {}).scrollTop, + }) + } + > + {this.props.renderMessage(message, tmp, () => this.measure(message))} +
+ ); + } + })} +
+
(this.dom_visualized_messages_bottom = node)} + > + {this.state.messages.map((message, _i) => { + if (this.compare(message, this.messages_med) > 0) { + var tmp = previous_message; + previous_message = message; + var i = _i; + return ( +
+ (this.dom_messages[i] = { + node: node, + message: message, + scrollTop: (this.dom_messages[i] || {}).scrollTop, + }) + } + > + {this.props.renderMessage(message, tmp, () => this.measure(message))} +
+ ); + } + })} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/InfiniteMessages/InfiniteMessages.scss b/twake/frontend/src/app/components/infinite-messages/infinite-messages.scss similarity index 100% rename from twake/frontend/src/app/components/InfiniteMessages/InfiniteMessages.scss rename to twake/frontend/src/app/components/infinite-messages/infinite-messages.scss diff --git a/twake/frontend/src/app/components/inline-tag-picker/inline-tag-picker.js b/twake/frontend/src/app/components/inline-tag-picker/inline-tag-picker.js new file mode 100644 index 0000000000..79fb62a435 --- /dev/null +++ b/twake/frontend/src/app/components/inline-tag-picker/inline-tag-picker.js @@ -0,0 +1,27 @@ +import React, { Component } from 'react'; +import './inline-tag-picker.scss'; + +export default class InlineTagPicker extends Component { + render() { + return this.props.available.map(item => { + return ( +
{ + let array = (this.props.value || []).map(a => a); + if (this.props.value.includes(item)) { + array = this.props.value.filter(val => item !== val); + } else { + array.push(item); + } + this.props.onChange(array); + }} + > + {item} +
+ ); + }); + } +} diff --git a/twake/frontend/src/app/components/InlineTagPicker/InlineTagPicker.scss b/twake/frontend/src/app/components/inline-tag-picker/inline-tag-picker.scss similarity index 100% rename from twake/frontend/src/app/components/InlineTagPicker/InlineTagPicker.scss rename to twake/frontend/src/app/components/inline-tag-picker/inline-tag-picker.scss diff --git a/twake/frontend/src/app/components/input-with-clip-board/input-with-clip-board.js b/twake/frontend/src/app/components/input-with-clip-board/input-with-clip-board.js new file mode 100755 index 0000000000..c2992f5c9a --- /dev/null +++ b/twake/frontend/src/app/components/input-with-clip-board/input-with-clip-board.js @@ -0,0 +1,60 @@ +import React, { Component } from 'react'; + +import Languages from 'app/features/global/services/languages-service'; +import Icon from 'components/icon/icon.js'; +import Tooltip from 'components/tooltip/tooltip.js'; +import Input from 'components/inputs/input.js'; +import InputWithButton from 'components/inputs/input-with-button.js'; + +export default class InputWithClipBoard extends Component { + /* + props = { + value : "", + disabled : true|false + } + */ + constructor(props) { + super(props); + this.props = props; + + this.state = { + i18n: Languages, + }; + + Languages.addListener(this); + this.inputElement = false; + } + componentWillUnmount() { + Languages.removeListener(this); + } + selectAll() { + this.inputElement.focus(); + this.inputElement.select(); + } + copy() { + this.inputElement.disabled = false; + this.inputElement.focus(); + this.inputElement.select(); + document.execCommand('copy'); + this.inputElement.disabled = this.props.disabled; + this.tooltip.openWithTimeOut(2); + } + render() { + return ( + (this.tooltip = obj)} + overable={false} + tooltip={Languages.t('components.input.copied', [], 'Copié')} + > + (this.inputElement = obj)} + btnAction={() => this.copy()} + icon="copy" + hideBtn={this.props.hideBtn} + value={this.props.value} + disabled={this.props.disabled} + /> + + ); + } +} diff --git a/twake/frontend/src/app/components/inputs/checkbox.js b/twake/frontend/src/app/components/inputs/checkbox.js new file mode 100755 index 0000000000..9e671aaeb1 --- /dev/null +++ b/twake/frontend/src/app/components/inputs/checkbox.js @@ -0,0 +1,92 @@ +import React, { Component } from 'react'; + +import './inputs.scss'; +import CheckIcon from '@material-ui/icons/CheckOutlined'; + +export default class Checkbox extends React.Component { + constructor(props) { + super(); + } + renderSwitch() { + var className = this.props.className || ''; + + if (this.props.big) { + className += ' big '; + } + if (this.props.medium) { + className += ' medium '; + } + if (this.props.small) { + className += ' small '; + } + + if ( + className.indexOf('medium') === className.indexOf('small') && + className.indexOf('big') === className.indexOf('small') && + className.indexOf('big') < 0 + ) { + className += ' medium'; + } + + return ( +
{ + if (!this.props.label && !this.props.disabled) { + this.props.onChange(!this.props.value); + } + }} + > +
+ +
+
+ ); + } + render() { + var parentClassName = ''; + + if (this.props.big) { + parentClassName += ' big '; + } + if (this.props.medium) { + parentClassName += ' medium '; + } + if (this.props.small) { + parentClassName += ' small '; + } + + if ( + parentClassName.indexOf('medium') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') < 0 + ) { + parentClassName += ' medium'; + } + + if (this.props.label) { + return ( +
{ + if (!this.props.disabled) { + this.props.onChange(!this.props.value); + } + }} + > + {this.renderSwitch()} +
{this.props.label}
+
+ ); + } else { + return this.renderSwitch(); + } + } +} diff --git a/twake/frontend/src/app/components/inputs/input-enter.js b/twake/frontend/src/app/components/inputs/input-enter.js new file mode 100755 index 0000000000..446111c4ee --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-enter.js @@ -0,0 +1,46 @@ +import React, { Component } from 'react'; + +import Input from './input.js'; +import Icon from 'components/icon/icon.js'; +import './inputs.scss'; + +export default class InputEnter extends React.Component { + constructor(props) { + super(); + } + render() { + var className = this.props.className || ''; + var parentClassName = ''; + + if (this.props.big) { + parentClassName += ' big '; + } + if (this.props.medium) { + parentClassName += ' medium '; + } + if (this.props.small) { + parentClassName += ' small '; + } + + if ( + parentClassName.indexOf('medium') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') < 0 + ) { + parentClassName += ' medium'; + } + + return ( +
+ + +
+ ); + } +} diff --git a/twake/frontend/src/app/components/inputs/input-icon.js b/twake/frontend/src/app/components/inputs/input-icon.js new file mode 100755 index 0000000000..4e43f8cb60 --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-icon.js @@ -0,0 +1,47 @@ +import React, { Component } from 'react'; + +import Input from './input.js'; +import Icon from 'components/icon/icon.js'; +import './inputs.scss'; + +export default class InputIcon extends React.Component { + constructor(props) { + super(); + } + render() { + var className = this.props.className || ''; + var parentClassName = ''; + + if (this.props.big) { + parentClassName += ' big '; + } + if (this.props.medium) { + parentClassName += ' medium '; + } + if (this.props.small) { + parentClassName += ' small '; + } + + if ( + parentClassName.indexOf('medium') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') === parentClassName.indexOf('small') && + parentClassName.indexOf('big') < 0 + ) { + parentClassName += ' medium'; + } + + return ( +
+ + +
+ ); + } +} diff --git a/twake/frontend/src/app/components/inputs/input-with-button.js b/twake/frontend/src/app/components/inputs/input-with-button.js new file mode 100644 index 0000000000..02bb606aad --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-with-button.js @@ -0,0 +1,53 @@ +import React, { Component } from 'react'; + +import Languages from 'app/features/global/services/languages-service'; +import './input-with-button.scss'; +import Icon from 'components/icon/icon.js'; +import Input from './input.js'; + +export default class InputWithButton extends Component { + /* + props = { + value : "", + disabled : true|false + } + */ + constructor(props) { + super(props); + this.props = props; + + this.state = { + i18n: Languages, + }; + + Languages.addListener(this); + this.inputElement = false; + } + + componentWillUnmount() { + Languages.removeListener(this); + } + + render() { + return ( +
+ { + this.inputElement = obj; + this.props.refInput && this.props.refInput(); + }} + {...this.props} + /> + {!this.props.hideBtn && ( +
this.props.btnAction()} + > + +
+ )} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/Inputs/InputWithButton.scss b/twake/frontend/src/app/components/inputs/input-with-button.scss similarity index 100% rename from twake/frontend/src/app/components/Inputs/InputWithButton.scss rename to twake/frontend/src/app/components/inputs/input-with-button.scss diff --git a/twake/frontend/src/app/components/inputs/input-with-color.js b/twake/frontend/src/app/components/inputs/input-with-color.js new file mode 100755 index 0000000000..5eeb997fc0 --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-with-color.js @@ -0,0 +1,129 @@ +import React, { Component } from 'react'; + +import MenusManager from 'app/components/menus/menus-manager.js'; +import ColorPicker from 'components/color-picker/color-picker.js'; +import Input from 'components/inputs/input.js'; +import './inputs.scss'; + +export default class InputWithColor extends React.Component { + constructor(props) { + super(); + } + componentWillMount() {} + outsideMenuListener() { + this.closeColorPicker(); + } + componentWillUnmount() { + document.removeEventListener('click', this.outsideClickListener); + } + componentDidMount() { + if (this.props.focusOnDidMount && this.input) { + this.input.focus(); + } + this.outsideClickListener = event => { + if ( + this.colorPickerIsOpen && + this.colorpicker_dom && + !this.colorpicker_dom.contains(event.target) && + document.contains(event.target) + ) { + this.outsideMenuListener(); + } + }; + this.outsideClickListener = this.outsideClickListener.bind(this); + document.addEventListener('click', this.outsideClickListener); + } + closeColorPicker() { + if (!this.colorPickerIsOpen) { + return; + } + + if (this.props.menu_level !== undefined) { + MenusManager.closeSubMenu(this.props.menu_level); + } else { + MenusManager.closeMenu(); + } + + this.colorPickerIsOpen = false; + } + openColorPicker() { + if (this.colorPickerIsOpen) { + return; + } + + var menu = [ + { + type: 'react-element', + reactElement: () => { + return ( + (this.colorpicker_dom = node)} + value={this.props.value[0]} + onChange={color => this.selectColor(color)} + /> + ); + }, + }, + ]; + var elementRect = window.getBoundingClientRect(this.color_dom); + elementRect.x = elementRect.x || elementRect.left; + elementRect.y = elementRect.y || elementRect.top; + if (this.props.menu_level !== undefined) { + MenusManager.openSubMenu(menu, elementRect, this.props.menu_level, 'bottom'); + } else { + MenusManager.openMenu(menu, elementRect, 'bottom'); + } + + setTimeout(() => { + this.colorPickerIsOpen = true; + }, 200); + } + selectColor(color) { + this.closeColorPicker(); + var value = [color, this.props.value[1]]; + this.onChange(value); + } + onChange(value) { + if (this.props.onChange) { + this.props.onChange(value); + } + } + render() { + if (!this.props.value[0]) { + this.onChange([ + ColorPicker.colors[parseInt(Math.random() * ColorPicker.colors.length)], + this.props.value[1], + ]); + } + return ( +
+
(this.color_dom = node)} + onClick={evt => { + this.openColorPicker(); + }} + > +
+
+
+ (this.input = obj)} + type="text" + placeholder={this.props.placeholder} + value={this.props.value[1]} + onKeyDown={e => { + if (e.keyCode == 13 && this.props.onEnter) { + this.props.onEnter(); + } + }} + onChange={evt => { + if (this.onChange) this.onChange([this.props.value[0], evt.target.value]); + }} + /> +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/inputs/input-with-icon.tsx b/twake/frontend/src/app/components/inputs/input-with-icon.tsx new file mode 100755 index 0000000000..f7a9932bf7 --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-with-icon.tsx @@ -0,0 +1,201 @@ +import React from 'react'; +import { Input, Col, Row } from 'antd'; + +import Emojione from 'components/emojione/emojione'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import EmojiPicker from 'components/emoji-picker/emoji-picker.js'; + +import './inputs.scss'; + +type PropsType = { [key: string]: any }; +type StateType = { [key: string]: any }; + +export default class InputWithIcon extends React.Component { + outsideClickListener: (event: any) => void = () => undefined; + input: any; + emojiPickerIsOpen: any; + emojipicker_dom: any; + allChanEmojies = [ + ':8ball:', + ':dart:', + ':joystick:', + ':video_game:', + ':bar_chart:', + ':crystal_ball:', + ':speech_balloon:', + ':bulb:', + ':deciduous_tree:', + ':palm_tree:', + ':earth_americas:', + ':open_file_folder:', + ':penguin:', + ':seedling:', + ':sailboat:', + ':fire_engine:', + ':scroll:', + ':newspaper:', + ':factory:', + ':package:', + ':mailbox:', + ':moneybag:', + ':smiley_cat:', + ':sunglasses:', + ]; + emoji_dom: any; + + UNSAFE_componentWillMount() { + this.randomizeEmojies(); + } + + randomizeEmojies() { + this.allChanEmojies.sort((a, b) => { + if (b === this.props.value[0]) { + return -1; + } + if (a === this.props.value[0]) { + return 1; + } + return Math.floor(Math.random() * 3) - 1; + }); + } + + outsideMenuListener() { + this.closeEmojiPicker(); + } + + componentWillUnmount() { + document.removeEventListener('click', this.outsideClickListener); + } + + componentDidMount() { + if (this.props.focusOnDidMount && this.input) { + this.input.focus(); + } + + this.outsideClickListener = event => { + if ( + this.emojiPickerIsOpen && + this.emojipicker_dom && + !this.emojipicker_dom.contains(event.target) && + document.contains(event.target) + ) { + this.outsideMenuListener(); + } + }; + + this.outsideClickListener = this.outsideClickListener.bind(this); + document.addEventListener('click', this.outsideClickListener); + } + + closeEmojiPicker() { + if (!this.emojiPickerIsOpen) { + return; + } + + if (this.props.menu_level !== undefined) { + MenusManager.closeSubMenu(this.props.menu_level); + } else { + MenusManager.closeMenu(); + } + + this.emojiPickerIsOpen = false; + } + + openEmojiPicker() { + if (this.emojiPickerIsOpen) { + return; + } + + let preferedEmojis = [this.props.value[0]]; + if (this.props.preferedEmoji) { + preferedEmojis = this.props.preferedEmoji; + } else { + this.randomizeEmojies(); + for (let i = 0; i < 5; i++) { + preferedEmojis[i + 1] = this.allChanEmojies[i]; + } + } + + const menu = [ + { + type: 'react-element', + className: 'menu-cancel-margin', + reactElement: () => { + return ( + (this.emojipicker_dom = node)} + onChange={(emoji: any) => this.selectEmoji(emoji)} + /> + ); + }, + }, + ]; + const elementRect = (window as any).getBoundingClientRect(this.emoji_dom); + elementRect.x = elementRect.x || elementRect.left; + elementRect.y = elementRect.y || elementRect.top; + if (this.props.menu_level !== undefined) { + MenusManager.openSubMenu(menu, elementRect, this.props.menu_level, 'bottom'); + } else { + MenusManager.openMenu(menu, elementRect, 'bottom', {}); + } + + setTimeout(() => { + this.emojiPickerIsOpen = true; + }, 200); + } + selectEmoji(emoji: any) { + this.closeEmojiPicker(); + const value = [emoji.native, this.props.value[1]]; + this.onChange(value); + } + onChange(value: any) { + if (this.props.onChange) { + this.props.onChange(value); + } + } + render() { + let icon = this.props.value[0]; + if (!this.props.value[0]) { + this.onChange([this.allChanEmojies[0], this.props.value[1]]); + icon = this.allChanEmojies[0]; + } + return ( + + + +
(this.emoji_dom = node)} + onClick={() => { + this.openEmojiPicker(); + }} + > + +
+ + + {(!this.props.children && ( + { + this.input = obj; + if (this.props.inputRef) this.props.inputRef(obj); + }} + type="text" + placeholder={this.props.placeholder} + value={this.props.value[1]} + onPressEnter={this.props.onEnter} + onChange={evt => { + if (this.onChange) this.onChange([this.props.value[0], evt.target.value]); + }} + /> + )) || + this.props.children} + +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/Inputs/InputWithSelect.scss b/twake/frontend/src/app/components/inputs/input-with-select.scss similarity index 100% rename from twake/frontend/src/app/components/Inputs/InputWithSelect.scss rename to twake/frontend/src/app/components/inputs/input-with-select.scss diff --git a/twake/frontend/src/app/components/inputs/input-with-select.tsx b/twake/frontend/src/app/components/inputs/input-with-select.tsx new file mode 100644 index 0000000000..6ff6e7c93a --- /dev/null +++ b/twake/frontend/src/app/components/inputs/input-with-select.tsx @@ -0,0 +1,105 @@ +import React, { useEffect, useState } from 'react'; +import { Input, Col, Row, Select, Typography, Button, Divider, Tooltip } from 'antd'; +import { ChannelType } from 'app/features/channels/types/channel'; +import { List, X } from 'react-feather'; +import Languages from 'app/features/global/services/languages-service'; +import './input-with-select.scss'; + +type PropsType = { + channel: ChannelType | undefined; + onChange: (array: string[]) => void; + groups: string[]; +}; + +const { Group } = Input; +const { Option } = Select; +const InputWithSelect = ({ groups, channel, onChange }: PropsType): JSX.Element => { + const [group, setGroup] = useState(channel?.channel_group || ''); + const [channelName, setChannelName] = useState(channel?.name || ''); + const [searchedGroup, setSearchedGroup] = useState(''); + const [displaySelector, setDisplaySelector] = useState( + channel?.channel_group ? true : false, + ); + + useEffect(() => { + onChange([group || '', channelName]); + }); + + return ( + + + {!displaySelector && ( + + + + + {Languages.t('components.locked_features.locked_guests_popup.or')} + + +
+ } + hideFooterDivider + footerAlign="center" + footerStyle={{ marginBottom: 16 }} + > + + + </Row> + + <Row justify="center"> + <Text + style={{ + textAlign: 'center', + width: '404px', + }} + children={Languages.t('components.locked_features.locked_only_office_popup.text')} + /> + </Row> + </ObjectModal> +)}; diff --git a/twake/frontend/src/app/components/locked-features-components/locked-guests-popup/locked-guests-popup.tsx b/twake/frontend/src/app/components/locked-features-components/locked-guests-popup/locked-guests-popup.tsx new file mode 100644 index 0000000000..7984bf6ead --- /dev/null +++ b/twake/frontend/src/app/components/locked-features-components/locked-guests-popup/locked-guests-popup.tsx @@ -0,0 +1,79 @@ +import { Button, Row, Typography } from 'antd'; +import ObjectModal from 'app/components/object-modal/object-modal'; +import React from 'react'; +import ModalManager from 'app/components/modal/modal-manager'; +import Languages from 'app/features/global/services/languages-service'; +import Emojione from 'app/components/emojione/emojione'; + +type PropsType = { + companySubscriptionUrl: string; +}; + +const { Text } = Typography; +const LockedGuestsPopup = ({ companySubscriptionUrl }: PropsType): JSX.Element => { + const onClickLearnMore = () => window.open(companySubscriptionUrl, 'blank'); + const onClickSkipForNow = () => ModalManager.close(); + + return ( + <ObjectModal + titleCenter + titleLevel={2} + title={ + <div + style={{ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + }} + > + {Languages.t('components.locked_features.locked_guests_popup.title')} + <Emojione type=":lock:" s128 /> + </div> + } + style={{ padding: 32 }} + hideFooterDivider + footerAlign="center" + footerStyle={{ marginBottom: 16 }} + footer={ + <div + style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 32 }} + > + <Button type="primary" size="large" onClick={onClickLearnMore}> + {Languages.t('components.locked_features.locked_guests_popup.learn_more_button')} + </Button> + <Typography.Text style={{ margin: '16px 0 ' }} strong> + {Languages.t('components.locked_features.locked_guests_popup.or')} + </Typography.Text> + <Button type="ghost" style={{ height: 36, width: 163 }} onClick={onClickSkipForNow}> + {Languages.t('components.locked_features.locked_guests_popup.skip_for_now_button')} + </Button> + </div> + } + > + <Row justify="center" style={{ margin: '12px 0 32px 0', height: '25px' }}> + <Typography.Title + level={3} + style={{ + textAlign: 'center', + margin: 0, + }} + > + {Languages.t('components.locked_features.locked_guests_popup.subtitle')} + </Typography.Title> + </Row> + + <Row justify="center"> + <Typography.Text + style={{ + textAlign: 'center', + width: '404px', + }} + > + {Languages.t('components.locked_features.locked_guests_popup.description')} + </Typography.Text> + </Row> + </ObjectModal> + ); +}; + +export default LockedGuestsPopup; diff --git a/twake/frontend/src/app/components/LockedFeaturesComponents/LockedHistoryBanner/LockedHistoryBanner.scss b/twake/frontend/src/app/components/locked-features-components/locked-history-banner/locked-history-banner.scss similarity index 100% rename from twake/frontend/src/app/components/LockedFeaturesComponents/LockedHistoryBanner/LockedHistoryBanner.scss rename to twake/frontend/src/app/components/locked-features-components/locked-history-banner/locked-history-banner.scss diff --git a/twake/frontend/src/app/components/locked-features-components/locked-history-banner/locked-history-banner.tsx b/twake/frontend/src/app/components/locked-features-components/locked-history-banner/locked-history-banner.tsx new file mode 100644 index 0000000000..545dca6be0 --- /dev/null +++ b/twake/frontend/src/app/components/locked-features-components/locked-history-banner/locked-history-banner.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Typography, Button } from 'antd'; +import Banner from 'app/components/banner/banner'; +import Emojione from 'app/components/emojione/emojione'; +import Languages from 'app/features/global/services/languages-service'; +import './locked-history-banner.scss'; +import consoleService from 'app/features/console/services/console-service'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; + +const { Title, Text } = Typography; +const LockedHistoryBanner = (): JSX.Element => { + + const companyId = useRouterCompany(); + + const onClickBtn = () => + window.open( + consoleService.getCompanySubscriptionUrl(companyId), + 'blank', + ); + + return ( + <Banner + type="ghost" + height={135} + className="locked-history-banner" + contentColumnStyle={{ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + height: '100%', + width: '380px', + }} + > + <div className="title-container"> + <Emojione type=":rocket:" s64 /> + <Title level={5} className="title"> + {Languages.t('components.locked_features.locked_history_banner.title')} + +
+ + {Languages.t('components.locked_features.locked_history_banner.description')} + + + + ); +}; + +export default LockedHistoryBanner; diff --git a/twake/frontend/src/app/components/locked-features-components/locked-invite-alert/index.tsx b/twake/frontend/src/app/components/locked-features-components/locked-invite-alert/index.tsx new file mode 100644 index 0000000000..28a3621650 --- /dev/null +++ b/twake/frontend/src/app/components/locked-features-components/locked-invite-alert/index.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { Typography, Alert } from 'antd'; +import Languages from 'app/features/global/services/languages-service'; +import { AlertTriangle } from 'react-feather'; +import { CompanyLimitsEnum, CompanyType } from 'app/features/companies/types/company'; +import consoleService from 'app/features/console/services/console-service'; + +type PropsType = { company: Partial; magicLink?: boolean }; + +const { Text, Link } = Typography; +const LockedInviteAlert = (props: PropsType): JSX.Element => { + const limit = props?.company?.plan?.limits?.[CompanyLimitsEnum.COMPANY_MEMBERS_LIMIT] || 0; + const onClickBtn = () => + window.open( + consoleService.getCompanySubscriptionUrl(props.company.id || ""), + 'blank', + ); + + return ( + + + + {Languages.t( + 'components.locked_features_components.locked_invite_alert.message_part_1', + [limit], + )} + {props.magicLink ? ( + <> + {Languages.t( + 'components.locked_features_components.locked_invite_alert.message_magic_link', + )} + + ) : ( + <> + + {Languages.t( + 'components.locked_features_components.locked_invite_alert.message_link', + )} + + {Languages.t( + 'components.locked_features_components.locked_invite_alert.message_part_2', + )} + + )} + + + } + /> + ); +}; + +export default LockedInviteAlert; diff --git a/twake/frontend/src/app/components/locked-features-components/locked-only-office-popup/locked-only-office-popup.tsx b/twake/frontend/src/app/components/locked-features-components/locked-only-office-popup/locked-only-office-popup.tsx new file mode 100644 index 0000000000..c1f25d67a9 --- /dev/null +++ b/twake/frontend/src/app/components/locked-features-components/locked-only-office-popup/locked-only-office-popup.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import ObjectModal from 'app/components/object-modal/object-modal'; +import { Button, Row, Typography } from 'antd'; +import ModalManager from 'app/components/modal/modal-manager'; +import Languages from 'app/features/global/services/languages-service'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import consoleService from 'app/features/console/services/console-service'; + +const { Title, Text } = Typography; +export default () => { + const companyId = useRouterCompany(); + return ( + + + + {Languages.t('components.locked_features.locked_guests_popup.or')} + + +
+ } + hideFooterDivider + footerAlign="center" + footerStyle={{ marginBottom: 16 }} + > + + + </Row> + + <Row justify="center"> + <Text + style={{ + textAlign: 'center', + width: '404px', + }} + children={Languages.t('components.locked_features.locked_only_office_popup.text')} + /> + </Row> + </ObjectModal> +)}; diff --git a/twake/frontend/src/app/components/locked-features-components/locked-workspace-popup/locked-workspace-popup.tsx b/twake/frontend/src/app/components/locked-features-components/locked-workspace-popup/locked-workspace-popup.tsx new file mode 100644 index 0000000000..e78882de78 --- /dev/null +++ b/twake/frontend/src/app/components/locked-features-components/locked-workspace-popup/locked-workspace-popup.tsx @@ -0,0 +1,74 @@ +import React from 'react'; +import ObjectModal from 'app/components/object-modal/object-modal'; +import { Button, Row, Typography } from 'antd'; +import ModalManager from 'app/components/modal/modal-manager'; +import Languages from 'app/features/global/services/languages-service'; +import consoleService from 'app/features/console/services/console-service'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; + +const { Title, Text } = Typography; +export default () => { + const companyId = useRouterCompany(); + return ( + <ObjectModal + titleCenter + titleLevel={2} + title={Languages.t('components.locked_features.locked_workspace_popup.title')} + titleTypographyStyle={{ textAlign: 'center', marginBottom: 32 }} + style={{ padding: 32 }} + contentStyle={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }} + footer={ + <div + style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: 32 }} + > + <Button + type="primary" + size="large" + style={{ marginTop: 8 }} + onClick={() => + window.open( + consoleService.getCompanySubscriptionUrl(companyId), + 'blank', + ) + } + > + {Languages.t('components.locked_features.locked_guests_popup.learn_more_button')} + </Button> + <Text style={{ margin: '16px 0 ' }} strong> + {Languages.t('components.locked_features.locked_guests_popup.or')} + </Text> + <Button + type="ghost" + style={{ height: 36, width: 163 }} + onClick={() => ModalManager.closeAll()} + > + {Languages.t('components.locked_features.locked_guests_popup.skip_for_now_button')} + </Button> + </div> + } + hideFooterDivider + footerAlign="center" + footerStyle={{ marginBottom: 16 }} + > + <Row justify="center" align="middle" className="bottom-margin"> + <Title + level={3} + children={Languages.t('components.locked_features.locked_workspace_popup.subtitle')} + style={{ + textAlign: 'center', + margin: 0, + }} + /> + </Row> + + <Row justify="center"> + <Text + style={{ + textAlign: 'center', + width: '404px', + }} + children={Languages.t('components.locked_features.locked_workspace_popup.text')} + /> + </Row> + </ObjectModal> +)}; diff --git a/twake/frontend/src/app/components/main-plus/main-plus.js b/twake/frontend/src/app/components/main-plus/main-plus.js new file mode 100755 index 0000000000..c4cf3a3ee2 --- /dev/null +++ b/twake/frontend/src/app/components/main-plus/main-plus.js @@ -0,0 +1,24 @@ +import React, { Component } from 'react'; +import Icon from 'components/icon/icon.js'; +import Menu from 'components/menus/menu.js'; +import './main-plus.scss'; + +export default class MainPlus extends Component { + constructor(props) { + super(props); + } + render() { + if (this.props.onClick) { + return ( + <div className="main_plus_button" onClick={this.props.onClick}> + <Icon type="plus" className="m-icon-small" /> + </div> + ); + } + return ( + <Menu menu={this.props.menu} className="main_plus_button" position={'top'}> + <Icon type="plus" className="m-icon-small" /> + </Menu> + ); + } +} diff --git a/twake/frontend/src/app/components/MainPlus/MainPlus.scss b/twake/frontend/src/app/components/main-plus/main-plus.scss similarity index 100% rename from twake/frontend/src/app/components/MainPlus/MainPlus.scss rename to twake/frontend/src/app/components/main-plus/main-plus.scss diff --git a/twake/frontend/src/app/components/member/user-parts.tsx b/twake/frontend/src/app/components/member/user-parts.tsx new file mode 100644 index 0000000000..1d26108d40 --- /dev/null +++ b/twake/frontend/src/app/components/member/user-parts.tsx @@ -0,0 +1,140 @@ +import React from 'react'; +import { Avatar, Badge, Tag } from 'antd'; +import { DashOutlined } from '@ant-design/icons'; +import { User } from 'react-feather'; +import Languages from 'app/features/global/services/languages-service'; +import RouterServices from 'app/features/router/services/router-service'; +import { UserType } from 'app/features/users/types/user'; +import UserService from 'app/features/users/services/current-user-service'; +import UsersService from 'app/features/users/services/current-user-service'; +import UserIcon from 'components/user/user'; +import { getUser } from 'app/features/users/hooks/use-user-list'; + +export type UserPartsType = { + avatar: JSX.Element; + name: string; + users: UserType[]; + companyRole: JSX.Element; +}; + +type PropsType = { + usersIds: string[]; + keepMyself?: boolean; + displayOnline?: boolean; + max?: number; + size?: number; +}; + +export const getUserParts = (props: PropsType): UserPartsType => { + const { companyId } = RouterServices.getStateFromRoute(); + const avatarSize = props.size || 20; + + let channelMembers = (props.usersIds || []).filter( + e => + props.keepMyself || + (props.usersIds.length || 0) === 1 || + e !== UsersService.getCurrentUserId(), + ); + channelMembers = channelMembers.filter((e, i) => channelMembers.indexOf(e) === i); + + let avatar: JSX.Element = ( + <Avatar size={avatarSize} icon={<User size={12} style={{ margin: 4 }} />} /> + ); + let channelName: string[] = []; + + const users: UserType[] = []; + + channelMembers?.forEach(userId => users.push(getUser(userId))); + + if (channelMembers?.length === 1) { + const avatarSrc = users[0]?.id ? ( + <UserIcon user={users[0]} withStatus={props.displayOnline} size={avatarSize} /> + ) : ( + UserService.getThumbnail(users[0]) + ); + avatar = ( + <Badge count={0} size="default" dot offset={[-4, 16]}> + <Avatar style={{ overflow: 'visible' }} size={avatarSize} src={avatarSrc} /> + </Badge> + ); + channelName = [UserService.getFullName(users[0])]; + } else if (channelMembers?.length || 0 > 1) { + avatar = ( + <Avatar.Group + maxCount={(props.max || 3) + 1} + maxStyle={{ + color: '#FFFFFF', + backgroundColor: `var(--grey-dark)`, + width: avatarSize, + height: avatarSize, + display: 'flex', + alignItems: 'center', + }} + > + {users + .filter((_, i) => i < (props.max || 3)) + .map(member => { + channelName.push(UserService.getFullName(member)); + return ( + member && ( + <Avatar key={member.id} size={avatarSize} src={UserService.getThumbnail(member)} /> + ) + ); + })} + {users.length > (props.max || 3) && ( + <Avatar + size={avatarSize} + style={{ backgroundColor: 'var(--grey-dark)' }} + icon={<DashOutlined />} + /> + )} + </Avatar.Group> + ); + } + + const roleOriginalString = UserService.getUserRole(users[0], companyId); + const companyRoleObject = getCurrentCompanyRoleObject(roleOriginalString); + const companyRole = + companyRoleObject.name !== 'unknown' ? ( + <Tag color={companyRoleObject.color}>{companyRoleObject.name}</Tag> + ) : ( + <></> + ); + + const shouldDisplayNotShowedUsersCount = users.length > (props.max || 3); + const notShowedUsersCount = users.length - (props.max || 3) + 1; /* myself */ + const name = `${channelName.join(', ')}${ + shouldDisplayNotShowedUsersCount + ? Languages.t('components.member.user_parts.and_more_user_text', [notShowedUsersCount]) + : '' + }`; + + return { + avatar, + name, + users, + companyRole, + }; +}; + +const getCurrentCompanyRoleObject = (role: string) => { + switch (role) { + case 'admin': + return { + color: 'var(--red)', + name: Languages.t('general.user.role.company.admin'), + }; + case 'member': + return { + color: 'var(--primary)', + name: Languages.t('general.user.role.company.member'), + }; + case 'guest': + return { + color: 'var(--grey-dark)', + name: Languages.t('general.user.role.company.guest'), + }; + default: + return { name: 'unknown' }; + } +}; diff --git a/twake/frontend/src/app/components/menus/menu-component.js b/twake/frontend/src/app/components/menus/menu-component.js new file mode 100755 index 0000000000..13f5422df1 --- /dev/null +++ b/twake/frontend/src/app/components/menus/menu-component.js @@ -0,0 +1,143 @@ +import React, { Component } from 'react'; + +import Icon from 'components/icon/icon.js'; +import Emojione from 'components/emojione/emojione'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import './menu.scss'; + +/* + One menu +*/ +export default class MenuComponent extends React.Component { + constructor(props) { + super(); + this.state = { + menus_manager: MenusManager, + }; + MenusManager.addListener(this); + } + componentWillUnmount() { + MenusManager.removeListener(this); + } + openSubMenu(dom_element, menu, level) { + var elementRect = window.getBoundingClientRect(dom_element); + elementRect.x = elementRect.x || elementRect.left; + elementRect.y = elementRect.y || elementRect.top; + MenusManager.openSubMenu(menu, elementRect, level); + } + closeSubMenu(level) { + MenusManager.closeSubMenu(level); + } + hoverMenu(dom_element, item) { + if (item.submenu && !item.submenu_replace) { + this.last_hovered = item; + this.openSubMenu(dom_element, item.submenu, this.props.level || 0); + } else { + this.closeSubMenu(this.props.level || 0); + } + } + clickMenu(dom_element, item, evt) { + if(Date.now() - this.props.openAt < 200 ){ + // When a menu is open and another one opens above it, you have to block the buttons for a while. Otherwise, the hovered option of the new menu will be clicked + return; + } + if (item.submenu_replace) { + MenusManager.openMenu(item.submenu, { x: evt.clientX, y: evt.clientY }, 'center'); + return; + } + if (item.onClick) { + var res = item.onClick(evt); + if (res !== false) { + MenusManager.closeMenu(); + } + } + } + render() { + return ( + <div + ref={node => (this.original_menu = node)} + className={ + 'menu-list ' + (this.props.withFrame ? 'as_frame ' : '') + this.props.animationClass + } + > + {(this.props.menu || []) + .filter(item => item && !item.hide) + .map((item, index) => { + if (item.type == 'separator') { + return <div key={'menu_' + index} className="menu-separator" />; + } else if (item.type == 'title') { + return ( + <div key={'menu_' + index} className={'menu-title ' + item.className}> + {item.text} + </div> + ); + } else if (item.type == 'text') { + return ( + <div + key={'menu_' + index} + ref={node => (item.ref = node)} + className={'menu-text ' + item.className} + onMouseEnter={evt => { + this.hoverMenu(item.ref, item); + }} + > + {item.text} + </div> + ); + } else if (item.type == 'react-element') { + return ( + <div + key={'menu_' + index} + className={'menu-custom ' + item.className} + onClick={item.onClick} + > + {typeof item.reactElement == 'function' + ? item.reactElement(this.props.level) + : item.reactElement} + </div> + ); + } else { + return ( + <div + key={'menu_' + index} + ref={node => (item.ref = node)} + className={ + 'menu ' + + item.className + + ' ' + + (this.state.menus_manager.max_level > this.props.level && + this.last_hovered == item + ? 'hovered ' + : '') + + (item.selected ? 'selected ' : '') + } + onMouseEnter={evt => { + this.hoverMenu(item.ref, item); + }} + onClick={evt => { + this.clickMenu(item.ref, item, evt); + }} + > + {item.icon && ( + <div className="icon"> + {typeof item.icon === 'string' ? <Icon type={item.icon} /> : item.icon} + </div> + )} + {item.emoji && ( + <div className="icon"> + <Emojione type={item.emoji} /> + </div> + )} + <div className="text">{item.text}</div> + <div className="more"> + {item.rightIcon && <Icon type={item.rightIcon} />} + {item.submenu && !item.submenu_replace && <Icon type="angle-right" />} + </div> + </div> + ); + } + })} + </div> + ); + } +} diff --git a/twake/frontend/src/app/components/menus/menu.js b/twake/frontend/src/app/components/menus/menu.js new file mode 100755 index 0000000000..12cf7e02ec --- /dev/null +++ b/twake/frontend/src/app/components/menus/menu.js @@ -0,0 +1,107 @@ +import React, { Component } from 'react'; + +import MenusManager from 'app/components/menus/menus-manager.js'; + +/* + One menu +*/ +export default class Menu extends React.Component { + /* + props = { + menu : menu object ex. {type:"menu", text:"Un menu", icon:"list"}, + {type:"menu", text:"Un menu avec sous menu", icon:"grid", submenu: [ + {text:"Sub menu 4", icon: "search"}, + {text:"Sub menu 5", icon: "search"}, + {text:"Sub menu 6", icon: "search"} + ]}, + {type:"menu", text:"Un menu avec sous menu", icon:"grid", submenu: [ + {type:"react-element", text:"Sub menu 6", icon: "search", reactElement:<div className="hello">salut</div>} + ]}, + {type:"separator"}, + {type:"text", text:"Du texte"} + {type:"react-element", reactElement: <Element />} + } + */ + + static closeAll() { + MenusManager.closeMenu(); + } + + constructor(props) { + super(); + this.state = { + menus_manager: MenusManager, + }; + MenusManager.addListener(this); + } + componentWillUnmount() { + if (this.props.onClose && this.open) { + this.props.onClose(); + } + MenusManager.removeListener(this); + } + openMenuFromParent(menu, rect, position) { + MenusManager.openMenu(menu, rect, position); + } + openMenu(evt) { + this.open = true; + evt.preventDefault(); + evt.stopPropagation(); + var elementRect = window.getBoundingClientRect(this.container); + elementRect.x = elementRect.x || elementRect.left; + elementRect.y = elementRect.y || elementRect.top; + this.previous_menus_id = MenusManager.openMenu( + this.props.menu, + elementRect, + this.props.position, + ); + if (this.props.onOpen) this.props.onOpen(); + } + shouldComponentUpdate(nextProps, nextState) { + if (nextProps.menu != this.props.menu && this.open) { + this.setState({}); + } + + if ( + (this.state.menus_manager.menus.length == 0 && this.previous_menus_number > 0) || + this.state.menus_manager.last_opened_id != this.previous_menus_id + ) { + if (this.open && this.props.onClose) { + this.props.onClose(); + } + this.open = false; + } + if (this.previous_menus_number != this.state.menus_manager.menus.length) { + this.previous_menus_number = this.state.menus_manager.menus.length; + } + + if (this.props.style !== nextProps.style || this.props.className !== nextProps.className) { + return true; + } + + return false; + } + render() { + return ( + <div + ref={node => (this.container = node)} + style={this.props.style} + onClick={evt => { + if (this.props.toggle) { + if (!this.open) { + this.openMenu(evt); + } else { + MenusManager.closeMenu(); + this.props.onClose && this.props.onClose(); + } + } else { + this.openMenu(evt); + } + }} + className={this.props.className} + > + {this.props.children} + </div> + ); + } +} diff --git a/twake/frontend/src/app/components/Menus/Menu.scss b/twake/frontend/src/app/components/menus/menu.scss similarity index 100% rename from twake/frontend/src/app/components/Menus/Menu.scss rename to twake/frontend/src/app/components/menus/menu.scss diff --git a/twake/frontend/src/app/components/menus/menus-body-layer.js b/twake/frontend/src/app/components/menus/menus-body-layer.js new file mode 100755 index 0000000000..94d3a9c0e1 --- /dev/null +++ b/twake/frontend/src/app/components/menus/menus-body-layer.js @@ -0,0 +1,225 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; + +import MenusManager from 'app/components/menus/menus-manager.js'; +import MenuComponent from './menu-component.js'; +import OutsideClickHandler from 'react-outside-click-handler'; + +/* + Where the menu will be displayed, this component should be in app.js (menus should be over all elements of the page) +*/ +export default class MenusBodyLayer extends React.Component { + constructor(props) { + super(); + this.state = { + menus_manager: MenusManager, + }; + this.menus_dom = null; + this.menu_observer = {}; + MenusManager.addListener(this); + this.outsideMenuListener = this.outsideMenuListener.bind(this); + this.outsideMenuListenerUp = this.outsideMenuListenerUp.bind(this); + + this.lastUpdatePosition = {}; + this.indexUpdatePosition = {}; + } + outsideMenuListener() { + //NOT WORKING + if ( + MenusManager.menus.length > 0 && + MenusManager.menus[MenusManager.menus.length - 1].allowClickOut + ) { + this.will_close_on_up = true; + } else { + this.will_close_on_up = false; + } + } + outsideMenuListenerUp() { + //NOT WORKING + if ( + MenusManager.menus.length > 0 && + MenusManager.menus[MenusManager.menus.length - 1].allowClickOut + ) { + if (this.will_close_on_up) { + MenusManager.closeMenu(); + } + } else { + this.will_close_on_up = false; + } + } + componentWillMount() { + if (!document.getElementById('context-menu-layer')) { + const div = document.createElement('div'); + div.setAttribute('id', 'context-menu-layer'); + document.body.appendChild(div); + } + } + componentWillUnmount() { + MenusManager.removeListener(this); + document.removeEventListener('mousedown', this.outsideClickListener); + document.removeEventListener('mouseup', this.outsideClickListenerUp); + + Object.keys(this.menu_observer).forEach(index => { + this.menu_observer[index].disconnect(); + }); + } + componentDidMount() { + var element = this.menus_dom; + this.outsideClickListener = event => { + if (!element.contains(event.target) && document.contains(event.target)) { + this.outsideMenuListener(); + } + }; + this.outsideClickListenerUp = event => { + if (!element.contains(event.target) && document.contains(event.target)) { + this.outsideMenuListenerUp(); + } + }; + document.addEventListener('mousedown', this.outsideClickListener); + document.addEventListener('mouseup', this.outsideClickListenerUp); + } + fixMenuPosition(node, item, index) { + if (!node) { + return; + } + + if (this.lastUpdatePosition[item.id] !== parseInt(new Date().getTime() / 1000)) { + this.lastUpdatePosition[item.id] = parseInt(new Date().getTime() / 1000); + this.indexUpdatePosition[item.id] = 0; + } else if (this.indexUpdatePosition[item.id] > 2) { + return; + } + this.indexUpdatePosition[item.id]++; + + if (this.menu_observer[index]) { + this.menu_observer[index].disconnect(); + } + + var config = { childList: true, subtree: true }; + this.menu_observer[index] = new MutationObserver(() => { + this.fixMenuPosition(node, item); + }); + this.menu_observer[index].observe(node, config); + + var nr = window.getBoundingClientRect(node); + nr.x = nr.x || nr.left; + nr.y = nr.y || nr.top; + var rect = JSON.parse(JSON.stringify(nr || {})); + rect.height = Math.max(node.offsetHeight, rect.height); + rect.bottom = rect.height + rect.y; + + var max_bottom = document.documentElement.clientHeight; + if (item.positionType === 'top') { + max_bottom = item.position.y; + } + + //Top + if (rect.top < 5 || (rect.top > 10 && item.position.marginTop > 0)) { + item.position.marginTop = Math.max(0, (item.position.marginTop || 0) - rect.top + 5); + MenusManager.notify(); + } + + //Bottom + if (item.position.marginTop === undefined || item.position.marginTop < 0) { + //Else we are on the top top + if ( + rect.bottom > Math.min(document.documentElement.clientHeight, max_bottom) - 5 || + (rect.bottom < Math.min(document.documentElement.clientHeight, max_bottom) - 10 && + item.position.marginTop < 0) + ) { + item.position.marginTop = Math.min( + 0, + (item.position.marginTop || 0) - + (rect.bottom - Math.min(document.documentElement.clientHeight, max_bottom) + 5), + ); + MenusManager.notify(); + } + } + + //Left + if (rect.left < 5 || (rect.left > 10 && item.position.marginLeft > 0)) { + item.position.marginLeft = Math.max(0, (item.position.marginLeft || 0) - rect.left + 5); + MenusManager.notify(); + } + //Right + else if ( + rect.right > document.documentElement.clientWidth - 5 || + (rect.right < document.documentElement.clientWidth - 10 && item.position.marginLeft < 0) + ) { + item.position.marginLeft = Math.min( + 0, + (item.position.marginLeft || 0) - (rect.right - document.documentElement.clientWidth + 5), + ); + MenusManager.notify(); + } + } + shouldComponentUpdate(nextProps, nextState) { + if (nextState.menus_manager.willClose !== this.willClose) { + this.willClose = nextState.menus_manager.willClose; + return true; + } + if (this.state.menus_manager.menus.length > 0 || this.last_menu_length > 0) { + this.last_menu_length = this.state.menus_manager.menus.length; + return true; + } + return false; + } + render() { + return ReactDOM.createPortal( + <OutsideClickHandler + onOutsideClick={() => { + MenusManager.closeMenu(); + }} + > + <div ref={node => (this.menus_dom = node)}> + {this.state.menus_manager.menus.map((item, i) => { + var menu = ( + <OutsideClickHandler + key={item.id} + onOutsideClick={() => { + if (i === this.state.menus_manager.menus.length - 1) { + MenusManager.closeSubMenu(item.level - 1); + } + }} + > + <div + ref={node => this.fixMenuPosition(node, item, i)} + style={{ + zIndex: 1050, + position: 'absolute', + transform: item.positionType === 'bottom' ? '' : 'translateY(-50%)', + left: item.position.x, + top: item.position.y, + marginTop: item.position.marginTop, + marginLeft: item.position.marginLeft, + }} + > + <MenuComponent + withFrame + menu={item.menu} + openAt={item.openAt} + level={item.level} + animationClass={ + this.state.menus_manager.willClose || item.willClose + ? 'fade_out' + : item.level === 0 || item.positionType + ? item.positionType === 'bottom' + ? 'skew_in_bottom_nobounce' + : item.left + ? 'skew_in_left_nobounce' + : 'skew_in_right_nobounce' + : 'fade_in' + } + /> + </div> + </OutsideClickHandler> + ); + + return menu; + })} + </div> + </OutsideClickHandler>, + document.getElementById('context-menu-layer'), + ); + } +} diff --git a/twake/frontend/src/app/components/menus/menus-manager.js b/twake/frontend/src/app/components/menus/menus-manager.js new file mode 100755 index 0000000000..52f2c1ddd9 --- /dev/null +++ b/twake/frontend/src/app/components/menus/menus-manager.js @@ -0,0 +1,179 @@ +import Observable from 'app/deprecated/CollectionsV1/observable.js'; +import Number from 'app/features/global/utils/Numbers'; +import Globals from 'app/features/global/services/globals-twake-app-service'; + +/** + * Menus manager service, choose where to generate menu + */ +class MenusManager extends Observable { + constructor() { + super(); + this.setObservableName('menus_manager'); + + window.menusService = this; + + this.menus = []; + this.lastOpen = 0; + this.willClose = false; + this.max_level = 0; + + var that = this; + Globals.window.addEventListener('keydown', function (evt) { + evt = evt || window.event; + var isEscape = false; + if ('key' in evt) { + isEscape = evt.key === 'Escape' || evt.key === 'Esc'; + } else { + isEscape = evt.keyCode === 27; + } + if (isEscape) { + that.closeMenu(); + } + }); + + this.closeMenu.bind(this); + this.openMenu.bind(this); + } + closeMenu() { + if (this.menus.length === 0) { + this.willClose = false; + return; + } + + if (new Date().getTime() - this.lastOpen < 500) { + return; + } + this.willClose = true; + + if (this.closeMenuTimeout) { + clearTimeout(this.closeMenuTimeout); + } + this.closeMenuTimeout = setTimeout(() => { + this.willClose = false; + this.menus = []; + this.notify(); + }, 200); + + this.notify(); + } + openMenu(menu, domRect, positionType, options) { + this.menus = []; + + if (this.closeMenuTimeout) { + this.willClose = false; + clearTimeout(this.closeMenuTimeout); + } + + if (!options) { + options = {}; + } + + var position = this.bestPosition(domRect, positionType, { margin: options.margin || 0 }); + + this.menus.push({ + menu: menu, + positionType: positionType, + position: position, + left: position.left, + openAt: Date.now(), + level: 0, + id: Number.unid(), + allowClickOut: options.allowClickOut !== undefined ? options.allowClickOut : true, + }); + this.last_opened_id = Number.unid(); + this.notify(); + this.lastOpen = new Date().getTime(); + + return this.last_opened_id; + } + openSubMenu(menu, domRect, level, positionType) { + this.max_level = level + 1; + this.closeSubMenu(level); + var position = this.bestPosition(domRect, positionType); + this.menus.push({ + menu: menu, + positionType: positionType, + position: position, + left: position.left, + openAt: Date.now(), + level: level + 1, + id: Number.unid(), + }); + + this.notify(); + } + closeSubMenu(level) { + this.max_level = level; + this.menus.forEach(item => { + if (item.level > level) { + item.willClose = true; + } + }); + this.notify(); + setTimeout(() => { + var new_menus = []; + this.menus.forEach(item => { + if (!(item.level > level && item.willClose)) { + new_menus.push(item); + } + }); + this.menus = new_menus; + this.notify(); + }, 200); + } + + bestPosition(rect, position, options) { + if (Globals.isReactNative) { + return {}; + } + + options = options || {}; + options.margin = options.margin || 0; + + rect = { + left: rect.left - options.margin, + x: rect.x - options.margin, + top: rect.top - options.margin, + y: rect.y - options.margin, + right: rect.right + options.margin, + bottom: rect.bottom + options.margin, + width: rect.width + 2 * options.margin, + height: rect.height + 2 * options.margin, + }; + + var x = rect.right || rect.x; + var y = rect.y; + + if (position === 'top' || position === 'bottom' || position === 'center') { + x = rect.x; + y = rect.bottom || rect.y; + if (position === 'top') { + y = rect.top || rect.y; + } + + return { + x: x + (rect.width || 0) / 2 - 100, + y: y, + left: false, + }; + } + + var left = false; + if (rect.right + 200 > document.documentElement.clientWidth) { + x = (rect.left || rect.x) - 200; + left = true; + } + if (x < 0) { + x = 0; + left = false; + } + + return { + x: x, + y: y + (rect.height || 0) / 2, + left: left, + }; + } +} + +export default new MenusManager(); diff --git a/twake/frontend/src/app/components/message-seen-by/message-seen-by.tsx b/twake/frontend/src/app/components/message-seen-by/message-seen-by.tsx new file mode 100644 index 0000000000..1109969672 --- /dev/null +++ b/twake/frontend/src/app/components/message-seen-by/message-seen-by.tsx @@ -0,0 +1,68 @@ +import UserBlock from 'app/molecules/grouped-rows/user'; +import { Modal, ModalContent } from 'app/atoms/modal'; +import messageApiClient from 'app/features/messages/api/message-api-client'; +import { UserType } from 'app/features/users/types/user'; +import React, { useEffect, useState } from 'react'; +import Avatar from 'app/atoms/avatar'; +import { useMessageSeenBy } from 'app/features/messages/hooks/use-message-seen-by'; +import Loader from '../loader/loader'; +import Languages from 'app/features/global/services/languages-service'; +import { Base } from 'app/atoms/text'; + +export default (): React.ReactElement => { + const { isOpen, closeSeenBy, seenMessage } = useMessageSeenBy(); + const [users, setUsers] = useState<UserType[]>(); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (isOpen && seenMessage) { + const { company_id, message_id, thread_id, workspace_id } = seenMessage; + + setLoading(true); + messageApiClient.seenBy(message_id, thread_id, company_id, workspace_id).then(users => { + setLoading(false); + setUsers(users); + }); + } + }, [open, seenMessage]); + + return ( + <Modal open={isOpen} onClose={() => closeSeenBy()} className="sm:w-[60vw] sm:max-w-2xl"> + <ModalContent + textCenter + title={Languages.t('components.message_seen_by.title', [], "Users who've seen the message")} + > + {loading ? ( + <div className="flex h-full justify-center items-center px-2"> + <Loader className="h-8 w-8 m-auto" /> + </div> + ) : ( + <div className="flex"> + <div className="w-[60vw] rounded-sm px-2 m-2"> + {users && users.length ? ( + users.map(user => ( + <UserBlock + avatar={ + <Avatar title={user.full_name ?? user.username} avatar={user.thumbnail} /> + } + title={user.full_name ?? user.username} + subtitle={user.email} + key={user.id} + /> + )) + ) : ( + <Base className='pt-4'> + {Languages.t( + 'components.message_seen_by.none_seen_it', + [], + 'No one has seen the message yet', + )} + </Base> + )} + </div> + </div> + )} + </ModalContent> + </Modal> + ); +}; diff --git a/twake/frontend/src/app/components/Modal/ModalComponent.scss b/twake/frontend/src/app/components/modal/modal-component.scss similarity index 100% rename from twake/frontend/src/app/components/Modal/ModalComponent.scss rename to twake/frontend/src/app/components/modal/modal-component.scss diff --git a/twake/frontend/src/app/components/modal/modal-component.tsx b/twake/frontend/src/app/components/modal/modal-component.tsx new file mode 100755 index 0000000000..a926bf4222 --- /dev/null +++ b/twake/frontend/src/app/components/modal/modal-component.tsx @@ -0,0 +1,50 @@ +import React, { useEffect, useMemo } from 'react'; +import { Modal } from 'antd'; +import './modal-component.scss'; +import ModalManager from 'app/components/modal/modal-manager'; + +let component: any = null; +export default () => { + const open = ModalManager.useWatcher(() => ModalManager.isOpen()); + + const eventClose = useMemo( + () => (evt: any) => { + if (evt.keyCode === 27 && ModalManager.canClose()) { + close(); + } + }, + [], + ); + + const close = () => { + if (ModalManager.canClose()) { + ModalManager.close(); + } + }; + + /* eslint-disable react-hooks/exhaustive-deps */ + useEffect(() => { + document.addEventListener('keydown', eventClose); + return () => { + document.removeEventListener('keydown', eventClose); + }; + }, []); + /* eslint-enable react-hooks/exhaustive-deps */ + + component = ModalManager.getComponent() || component; + + return ( + <Modal + onCancel={close} + centered + closable={false} + title={null} + visible={open} + footer={null} + destroyOnClose={true} + width={ModalManager.getPosition()?.size?.width || '700px'} + > + {component} + </Modal> + ); +}; diff --git a/twake/frontend/src/app/components/modal/modal-manager.ts b/twake/frontend/src/app/components/modal/modal-manager.ts new file mode 100755 index 0000000000..04a3c7c0b6 --- /dev/null +++ b/twake/frontend/src/app/components/modal/modal-manager.ts @@ -0,0 +1,81 @@ +import Observable from 'app/deprecated/Observable/Observable'; +import MenusManager from 'app/components/menus/menus-manager.js'; + +class ModalManagerService extends Observable { + static service: ModalManagerService = new ModalManagerService(); + private component: any[] = []; + private popupStates: any = {}; + private position: any = null; + private mountedComponent: any = null; + private closing = false; + private creationTimeout: any = null; + + getPosition() { + return this.position; + } + + updateHighlight(highlight: any) { + if (this.position) this.position.highlight = highlight; + this.notify(); + } + + open(component: any, position: any, canClose?: boolean, clearState?: any) { + this.close(); + + this.mountedComponent = null; + + this.creationTimeout && clearTimeout(this.creationTimeout); + this.creationTimeout = setTimeout(() => { + this.component = []; + this.position = position || {}; + MenusManager.closeMenu(); + if (clearState) { + delete this.popupStates[clearState]; + } + this.component.push({ component: component, canClose: canClose !== false }); + this.notify(); + }, 100); + } + + isOpen() { + return this.component.length > 0; + } + + close() { + if (this.closing) { + return false; + } + if (this.isOpen()) { + this.closing = true; + (this.mountedComponent || {}).onMediumPopupClose && + this.mountedComponent.onMediumPopupClose(); + + this.mountedComponent = null; + this.component.splice(-1, 1); + this.notify(); + this.closing = false; + } + } + closeAll() { + if (this.isOpen()) { + (this.mountedComponent || {}).onMediumPopupClose && + this.mountedComponent.onMediumPopupClose(); + + this.mountedComponent = null; + this.component = []; + this.notify(); + } + } + canClose() { + if (this.isOpen()) { + return this.component[this.component.length - 1].canClose; + } + return null; + } + getComponent() { + return this.component[this.component.length - 1]?.component || ''; + } +} + +const ModalManager = ModalManagerService.service; +export default ModalManager; diff --git a/twake/frontend/src/app/components/new-version/new-version-component.tsx b/twake/frontend/src/app/components/new-version/new-version-component.tsx new file mode 100644 index 0000000000..bf17a1455a --- /dev/null +++ b/twake/frontend/src/app/components/new-version/new-version-component.tsx @@ -0,0 +1,108 @@ +import React, { useMemo, useState } from 'react'; +import { Col, Row, Typography } from 'antd'; + +import Api from 'app/features/global/framework/api-service'; +import Banner from 'app/components/banner/banner'; +import Emojione from 'app/components/emojione/emojione'; +import Languages from 'app/features/global/services/languages-service'; +import Globals from 'app/features/global/services/globals-twake-app-service'; +import ModalManager from 'app/components/modal/modal-manager'; +import NewVersionModal from './new-version-modal'; +import { ServerInfoType } from 'app/features/global/services/init-service'; + +let lastScrape = 0; + +const NewVersionComponent = (): JSX.Element => { + const [displayBanner, setDisplayBanner] = useState<boolean>(false); + + const compareVersion: (v1: string, v2: string) => number = (v1: string, v2: string) => { + const toNumber: (v: string) => number = (v: string) => { + const a = v.split('.').map((s: string) => parseInt(s.replace(/[^0-9]/g, ''))); + return 1000000 * (1000 * a[0] + a[1]) + a[2]; + }; + return toNumber(v1) - toNumber(v2); + }; + + useMemo(() => { + const getConfiguration = async () => { + if (new Date().getTime() - lastScrape < 15 * 60 * 1000) { + return; + } + lastScrape = new Date().getTime(); + + const config = await Api.get<ServerInfoType>( + '/internal/services/general/v1/server', + undefined, + false, + { + disableJWTAuthentication: true, + }, + ); + const currentVersion: string = Globals.version.version_detail; + const newestVersion: string = config?.version?.current || ''; + const minimalWebVersion: string = config?.version?.minimal?.web || ''; + + const shouldDisplayModal: boolean = + minimalWebVersion && compareVersion(minimalWebVersion, currentVersion) > 0 ? true : false; + const shouldDisplayBanner: boolean = + newestVersion && compareVersion(newestVersion, currentVersion) > 0 && !shouldDisplayModal + ? true + : false; + + if (shouldDisplayModal) { + return ModalManager.open( + <NewVersionModal />, + { + position: 'center', + size: { width: '600px' }, + }, + false, + ); + } + + if (shouldDisplayBanner) { + return setDisplayBanner(shouldDisplayBanner); + } + }; + + document.addEventListener('visibilitychange', () => { + getConfiguration(); + }); + window.addEventListener('focus', () => { + getConfiguration(); + }); + getConfiguration(); + }, []); + + return ( + <> + {displayBanner && ( + <Banner + height={32} + type="primary" + content={ + <Row align="middle" gutter={[8, 0]}> + <Col> + <b>{Languages.t('components.newversion.new_version_component.row.part_1')}</b>,{' '} + {Languages.t('components.newversion.new_version_component.row.part_2')}{' '} + <Emojione type="rocket" /> + </Col> + <Col> + <Typography.Link + style={{ color: 'var(--white)' }} + underline + onClick={() => window.location.reload()} + > + {Languages.t('components.newversion.new_version_component.link')} + </Typography.Link> + </Col> + </Row> + } + closable + onClose={() => setDisplayBanner(false)} + /> + )} + </> + ); +}; +export default NewVersionComponent; diff --git a/twake/frontend/src/app/components/new-version/new-version-modal.tsx b/twake/frontend/src/app/components/new-version/new-version-modal.tsx new file mode 100644 index 0000000000..f4415f29a4 --- /dev/null +++ b/twake/frontend/src/app/components/new-version/new-version-modal.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import ObjectModal from '../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import Emojione from '../emojione/emojione'; +import { Button } from 'antd'; + +const NewVersionModal = () => { + const onClickBtn = () => { + return window.location.reload(); + }; + + return ( + <ObjectModal + title={ + <> + {Languages.t('components.newversion.new_version_modal.title')} <Emojione type="rocket" /> + </> + } + footer={ + <Button type="primary" onClick={onClickBtn}> + {Languages.t('scenes.app.header.disconnected.reload')} + </Button> + } + > + <div className="x-margin"> + <b>{Languages.t('components.newversion.new_version_component.row.part_1')}</b>,{' '} + {Languages.t('components.newversion.new_version_component.row.part_2')} + </div> + </ObjectModal> + ); +}; + +export default NewVersionModal; diff --git a/twake/frontend/src/app/components/object-modal/deprecated-object-modal.js b/twake/frontend/src/app/components/object-modal/deprecated-object-modal.js new file mode 100755 index 0000000000..431a1d128d --- /dev/null +++ b/twake/frontend/src/app/components/object-modal/deprecated-object-modal.js @@ -0,0 +1,118 @@ +import React, { Component } from 'react'; +import Icon from 'components/icon/icon.js'; +import PerfectScrollbar from 'react-perfect-scrollbar'; +import Tabs from 'components/tabs/tabs.js'; +import './deprecated-object-modal.scss'; +import { Divider } from 'antd'; + +export class ObjectModalTitle extends Component { + render() { + return ( + <div className={'modal_title ' + this.props.className} style={this.props.style}> + {this.props.children} + </div> + ); + } +} +//ObjectModalSeparator +export class ObjectModalSeparator extends Component { + render() { + return <div className="separator"></div>; + } +} +//ObjectModalSectionTitle +export class ObjectModalSectionTitle extends Component { + render() { + return ( + <div + style={{ + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + marginBottom: this.props.smallMargin ? '16px' : '', + }} + > + <b>{this.props.title || this.props.children}</b> + <div>{this.props.action}</div> + </div> + ); + } +} + +// ObjectModalFormTitle +export class ObjectModalFormTitle extends Component { + render() { + return ( + <div className={'section_title ' + this.props.className} style={this.props.style}> + {this.props.icon && <Icon type={this.props.icon} className="m-icon-small" />} + <span>{this.props.name}</span> + </div> + ); + } +} + +export class ObjectModal extends Component { + constructor(props) { + super(); + this.state = {}; + } + render() { + return ( + <div className={'object_modal ' + this.props.className}> + <div className="top_right_buttons"> + {this.props.onEdit && ( + <div className="square_button" onClick={this.props.onEdit}> + <Icon type="edit-alt" className="m-icon-small" /> + </div> + )} + {this.props.onClose && ( + <div className="square_button" onClick={this.props.onClose}> + <Icon type="times" className="m-icon-small" /> + </div> + )} + </div> + + <div className={!this.props.noCloseButton ? 'title' : ''}>{this.props.title}</div> + + {this.props.tabs && ( + <Tabs + tabs={this.props.tabs.map(item => { + return { + title: item.title || '', + render: ( + <div className="body"> + <PerfectScrollbar options={{ suppressScrollX: true }} component="div"> + {item.render} + </PerfectScrollbar> + </div> + ), + }; + })} + /> + )} + + {!this.props.tabs && ( + <div className="body"> + {!!this.props.noScrollBar && ( + <div className="child-with-margin">{this.props.children}</div> + )} + {!this.props.noScrollBar && ( + <PerfectScrollbar options={{ suppressScrollX: true }} component="div"> + {this.props.children} + </PerfectScrollbar> + )} + </div> + )} + + {this.props.footer && <div className="separator" style={{ marginTop: 0 }} />} + {this.props.footer && ( + <div className="footer bottom-margin"> + <Divider /> + <div className="x-margin">{this.props.footer}</div> + </div> + )} + </div> + ); + } +} diff --git a/twake/frontend/src/app/components/ObjectModal/DeprecatedObjectModal.scss b/twake/frontend/src/app/components/object-modal/deprecated-object-modal.scss similarity index 100% rename from twake/frontend/src/app/components/ObjectModal/DeprecatedObjectModal.scss rename to twake/frontend/src/app/components/object-modal/deprecated-object-modal.scss diff --git a/twake/frontend/src/app/components/ObjectModal/ObjectModal.scss b/twake/frontend/src/app/components/object-modal/object-modal.scss similarity index 100% rename from twake/frontend/src/app/components/ObjectModal/ObjectModal.scss rename to twake/frontend/src/app/components/object-modal/object-modal.scss diff --git a/twake/frontend/src/app/components/object-modal/object-modal.tsx b/twake/frontend/src/app/components/object-modal/object-modal.tsx new file mode 100644 index 0000000000..f07d95e7aa --- /dev/null +++ b/twake/frontend/src/app/components/object-modal/object-modal.tsx @@ -0,0 +1,94 @@ +import React, { FC } from 'react'; + +import classNames from 'classnames'; +import { Divider, Layout, Typography, Col, Row } from 'antd'; + +import ModalManager from 'app/components/modal/modal-manager'; +import Icon from 'components/icon/icon.js'; + +import './object-modal.scss'; + +type PropsType = { + title?: string | JSX.Element; + closable?: boolean; + children?: React.Component | JSX.Element | any; + footer?: React.Component | JSX.Element | any; + hideFooterDivider?: boolean; + footerAlign?: 'start' | 'end' | 'center' | 'space-around' | 'space-between' | undefined; + titleCenter?: boolean; + style?: React.CSSProperties; + headerStyle?: React.CSSProperties; + footerStyle?: React.CSSProperties; + titleLevel?: 5 | 1 | 2 | 3 | 4 | undefined; + titleColor?: string; + colTitleStyle?: React.CSSProperties; + contentStyle?: React.CSSProperties; + titleTypographyStyle?: React.CSSProperties; + className?: string; + footerDividerStyle?: React.CSSProperties; + onClose?: () => void; +}; + +const { Header, Content, Footer } = Layout; +const ObjectModal: FC<PropsType> = (props: PropsType) => { + return ( + <Layout + className={classNames('modal-layout', props.className)} + hasSider={false} + style={props.style || {}} + > + <Header className="modal-layout-header" style={props.headerStyle || {}}> + <Row justify="space-between" align="middle" className="modal-layout-row" wrap={false}> + {props.titleCenter && <Col style={{ width: 32 }}></Col>} + {props.title && ( + <Col style={props.colTitleStyle}> + <Typography.Title + level={props.titleLevel || 5} + style={{ + margin: 0, + marginTop: props.titleCenter ? 8 : 0, + color: props.titleColor, + ...props.titleTypographyStyle, + }} + > + {props.title} + </Typography.Title> + </Col> + )} + {(props.closable === true && ( + <Col> + <Icon + type="times" + className={`m-icon-small square-button ${ + props.headerStyle?.backgroundColor ? 'red' : '' + }`} + onClick={() => (props?.onClose ? props.onClose() : ModalManager.closeAll())} + /> + </Col> + )) || <Col style={{ width: 32 }}></Col>} + </Row> + </Header> + {props.children && <Content style={props.contentStyle}>{props.children}</Content>} + {props.footer && ( + <Footer className="modal-layout-footer"> + {!props.hideFooterDivider && ( + <Divider className="y-margin" style={props.footerDividerStyle} /> + )} + <Row align="middle" justify={props.footerAlign || 'end'}> + <Col + style={{ + marginBottom: props.footerAlign === 'center' ? 54 : 16, + marginRight: !props.footerAlign ? 16 : 0, + ...props.footerStyle, + }} + > + {props.footer} + </Col> + </Row> + </Footer> + )} + </Layout> + ); +}; + +export default ObjectModal; diff --git a/twake/frontend/src/app/components/on-boarding/account-status-component.tsx b/twake/frontend/src/app/components/on-boarding/account-status-component.tsx new file mode 100644 index 0000000000..88e6545ece --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/account-status-component.tsx @@ -0,0 +1,78 @@ +import React from 'react'; + +import Banner from 'app/components/banner/banner'; +import { Button, Typography } from 'antd'; +import Languages from 'app/features/global/services/languages-service'; +import ModalManager from 'app/components/modal/modal-manager'; +import UnverifiedAccount from './popups/unverified-account'; +import BlockedAccount from './popups/blocked-account'; +import InitService from 'app/features/global/services/init-service'; +import { useCurrentUser } from 'app/features/users/hooks/use-current-user'; + +const AccountStatusComponent = (): JSX.Element => { + const { user } = useCurrentUser(); + const maxUnverifiedDays = + InitService.server_infos?.configuration?.accounts?.console?.max_unverified_days || 7; + const oneDay = 1000 * 60 * 60 * 24; + const periodLimit = (user?.created_at || 0) + maxUnverifiedDays * oneDay; + const daysLeft = Math.ceil((periodLimit - Date.now()) / oneDay); + + if (!user || InitService.server_infos?.configuration?.accounts?.type !== 'console') { + return <></>; + } + + const showBlockedModal = () => { + if (InitService.server_infos?.configuration?.accounts?.type === 'console') + return ModalManager.open( + <BlockedAccount email={user?.email} />, + { + position: 'center', + size: { width: '600px' }, + }, + false, + ); + }; + + const showUnverifiedModal = () => { + if (InitService.server_infos?.configuration?.accounts?.type === 'console') + return ModalManager.open( + <UnverifiedAccount daysLeft={daysLeft} limit={maxUnverifiedDays} email={user.email} />, + { + position: 'center', + size: { width: '600px' }, + }, + ); + }; + + if (!user.is_verified && daysLeft <= 0) { + showBlockedModal(); + } + + const showBanner = !user.is_verified; + return ( + <> + {showBanner && ( + <Banner + type="important" + content={ + <div style={{ display: 'flex', alignItems: 'center' }}> + <Typography.Title level={5} style={{ marginBottom: 0, color: 'var(--white)' }}> + {Languages.t('components.account_verification_status_sentence', [ + Languages.t('components.account_verication_status_unverified'), + ])} + </Typography.Title> + <Button + style={{ marginLeft: 17, height: 32, color: 'var(--red)' }} + onClick={showUnverifiedModal} + > + {Languages.t('general.verify')} + </Button> + </div> + } + /> + )} + </> + ); +}; + +export default AccountStatusComponent; diff --git a/twake/frontend/src/app/components/on-boarding/company-billing-banner.tsx b/twake/frontend/src/app/components/on-boarding/company-billing-banner.tsx new file mode 100644 index 0000000000..9f676d837f --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/company-billing-banner.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Row, Typography } from 'antd'; +import Banner from '../banner/banner'; +import { CompanyType } from 'app/features/companies/types/company'; +import Groups from 'app/deprecated/workspaces/groups.js'; +import Languages from 'app/features/global/services/languages-service'; +import { AlertTriangle } from 'react-feather'; +import consoleService from 'app/features/console/services/console-service'; + +type PropsType = { + companyId: string; +}; + +const { Link } = Typography; +export default ({ companyId }: PropsType): JSX.Element => { + const companySubscriptionUrl = consoleService.getCompanySubscriptionUrl(companyId); + const userGroups: { [key: string]: CompanyType } = Groups.user_groups; + const currentUserGroup = userGroups[companyId]; + const isCurrentUserAdminOrOwner = + currentUserGroup?.role === 'admin' || currentUserGroup?.role === 'owner'; + + const onClickLink = () => window.open(companySubscriptionUrl, 'blank'); + + const shouldDisplayBanner = currentUserGroup?.plan?.billing?.status === 'warning'; + return shouldDisplayBanner ? ( + <Banner type="important"> + <Row align="middle"> + <AlertTriangle size={24} /> + <div className="small-x-margin"> + {Languages.t( + isCurrentUserAdminOrOwner + ? 'components.on_boarding.company_billing_banner.admin_or_owner_text' + : 'components.on_boarding.company_billing_banner.guest_or_member_text', + )} + </div> + {isCurrentUserAdminOrOwner && ( + <Link onClick={onClickLink}> + {Languages.t('components.on_boarding.company_billing_banner.link')} + </Link> + )} + </Row> + </Banner> + ) : ( + <></> + ); +}; diff --git a/twake/frontend/src/app/components/on-boarding/company-status-component.tsx b/twake/frontend/src/app/components/on-boarding/company-status-component.tsx new file mode 100644 index 0000000000..d9ad1c9f6e --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/company-status-component.tsx @@ -0,0 +1,76 @@ +import React, { useEffect } from 'react'; +import ModalManager from 'app/components/modal/modal-manager'; +import UserService from 'app/features/users/services/current-user-service'; +import WelcomeOnTwake from './popups/welcome-on-twake'; +import DepreciatedCollections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import InitService from 'app/features/global/services/init-service'; +import Groups from 'app/deprecated/workspaces/groups.js'; +import { CompanyType } from 'app/features/companies/types/company'; +import BlockedCompany from './popups/blocked-company'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import useRouterWorkspace from 'app/features/router/hooks/use-router-workspace'; + +const CompanyStatusComponent = (): JSX.Element => { + const companyId = useRouterCompany(); + const workspaceId = useRouterWorkspace(); + const user = UserService.getCurrentUser(); + const onboarding: string | null = localStorage.getItem(`onboarding_${companyId}`); + const workspace = DepreciatedCollections.get('workspaces').find(workspaceId); + + useEffect(() => { + if (InitService.server_infos?.configuration?.accounts?.type === 'console') { + isNewAccount(); + } + + isBlockedCompany(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [companyId]); + + const isNewCompany = (): boolean => { + const oneDay = 1000 * 60 * 60 * 24; + const createdDay = workspace?.group?.stats?.created_at; + const currentDay = Date.now(); + const currentPeriod = Math.round(Math.round(currentDay - createdDay) / oneDay); + + return currentPeriod <= 7 ? true : false; + }; + + const isNewAccount = () => { + if (!workspace?.id) return; + + const isNewUser: boolean = + onboarding !== 'completed' && + workspace?.group?.stats?.total_members <= 1 && + isNewCompany() && + !user?.is_verified; + + if (isNewUser) { + localStorage.setItem(`onboarding_${companyId}`, 'completed'); + return ModalManager.open(<WelcomeOnTwake email={user.email} />, { + position: 'center', + size: { width: '600px' }, + }); + } + }; + + const isBlockedCompany = () => { + if (!companyId) return; + const userGroups: { [key: string]: CompanyType } = Groups.user_groups; + const currentGroup = userGroups[companyId]; + + if (currentGroup?.plan?.billing?.status === 'error') { + return ModalManager.open( + <BlockedCompany />, + { + position: 'center', + size: { width: '600px' }, + }, + false, + ); + } + }; + + return <></>; +}; + +export default CompanyStatusComponent; diff --git a/twake/frontend/src/app/components/on-boarding/popups/add-mails-in-workspace.tsx b/twake/frontend/src/app/components/on-boarding/popups/add-mails-in-workspace.tsx new file mode 100644 index 0000000000..9a7dbff72c --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/popups/add-mails-in-workspace.tsx @@ -0,0 +1,81 @@ +import React, { useState } from 'react'; +import { Button, Col, Row, Typography } from 'antd'; +import AutoHeight from '../../auto-height/auto-height'; +import ObjectModal from '../../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import ModalManager from 'app/components/modal/modal-manager'; +import ConsoleService from 'app/features/console/services/console-service'; +import RouterServices from 'app/features/router/services/router-service'; +import WorkspacesUsers from 'app/features/workspace-members/services/workspace-members-service'; + +export default (): JSX.Element => { + const { companyId, workspaceId } = RouterServices.getStateFromRoute(); + const [emails, _setEmails] = useState<string[]>([]); + const [loading, setLoading] = useState<boolean>(false); + + const setEmails = (str: string) => + _setEmails(WorkspacesUsers.fullStringToEmails(str) as string[]); + + const onChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => setEmails(e.target.value); + + const onClickButton = async () => { + setLoading(true); + + return await ConsoleService.addMailsInWorkspace({ + workspace_id: workspaceId || '', + company_id: companyId || '', + emails, + }).finally(() => { + setLoading(false); + return ModalManager.close(); + }); + }; + + return ( + <ObjectModal + title={Languages.t('components.add_mails_workspace.title_1')} + closable + style={{ height: 600 }} + titleLevel={2} + titleCenter + hideFooterDivider + footerAlign="center" + footer={ + <Row className="x-margin" justify="center"> + <Button onClick={onClickButton} type="primary" size="large" loading={loading}> + {Languages.t('components.add_mails_workspace.button')} + </Button> + </Row> + } + > + <Row + className="x-margin" + style={{ padding: '0 16px', marginTop: 16, marginBottom: 62 }} + justify="center" + > + <Typography.Text + style={{ textAlign: 'center', width: '464px', fontSize: 17, height: '44px' }} + > + {Languages.t('components.add_mails_workspace.title_2')} + </Typography.Text> + </Row> + + <Row className="x-margin" style={{ marginBottom: 12, paddingTop: 32 }} justify="center"> + <Col style={{ width: 400 }}> + <AutoHeight + minHeight="110px" + maxHeight="300px" + onChange={onChange} + placeholder={Languages.t('components.add_mails_workspace.text_area_placeholder')} + /> + </Col> + </Row> + + <Row className="x-margin" style={{ display: 'flex', justifyContent: 'center' }}> + <Typography.Text type="secondary" style={{ width: 380, fontSize: 13, height: 32 }}> + {Languages.t('scenes.app.popup.adduser.adresses_message')} + </Typography.Text> + </Row> + </ObjectModal> + ); +}; diff --git a/twake/frontend/src/app/components/on-boarding/popups/blocked-account.tsx b/twake/frontend/src/app/components/on-boarding/popups/blocked-account.tsx new file mode 100644 index 0000000000..b40dca9335 --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/popups/blocked-account.tsx @@ -0,0 +1,94 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import React, { useState } from 'react'; +import { Button, Row, Typography } from 'antd'; +import ObjectModal from '../../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import ConsoleService from 'app/features/console/services/console-service'; +import LoginService from 'app/features/auth/login-service'; + +type PropsType = { + email: string; +}; + +export default ({ email }: PropsType): JSX.Element => { + const [loading, setLoading] = useState<boolean>(false); + + const onClickButton = () => { + setLoading(true); + return ConsoleService.verifyMail().finally(() => setLoading(false)); + }; + + return ( + <ObjectModal + title={Languages.t('components.account_verification_status_sentence', [ + Languages.t('components.account_verication_status_blocked'), + ])} + titleColor="var(--white)" + titleCenter + headerStyle={{ backgroundColor: 'var(--red)', color: 'var(--white)', height: 76 }} + hideFooterDivider + footerAlign="center" + footer={ + <> + <Button type="ghost" size="small" onClick={onClickButton} loading={loading}> + {Languages.t('general.re_send')} + </Button> + + <Row justify="center" style={{ marginTop: 16 }}> + <a className="blue_link" onClick={() => LoginService.logout()}> + {Languages.t('scenes.apps.account.account.logout')} + </a> + </Row> + </> + } + > + <Row justify="center" style={{ marginTop: 36 }}> + <Typography.Title + level={3} + style={{ + textAlign: 'center', + margin: 0, + width: 493, + }} + > + {Languages.t('components.blocked_account.trial_period_over')} + </Typography.Title> + </Row> + + <Row justify="center" style={{ marginTop: 24 }}> + <Typography.Text + style={{ + textAlign: 'center', + height: 22, + }} + > + {Languages.t('components.unverified_account.verification_details')} + </Typography.Text> + </Row> + + <Row justify="center" style={{ marginTop: 12 }}> + <Typography.Text + strong + style={{ + textAlign: 'center', + height: '22px', + }} + > + {email} + </Typography.Text> + </Row> + + <Row justify="center" style={{ marginTop: 32, marginBottom: 8 }}> + <Typography.Text + style={{ + textAlign: 'center', + fontSize: 15, + height: '22px', + }} + > + {Languages.t('components.unverified_account.re_send_email')} + </Typography.Text> + </Row> + </ObjectModal> + ); +}; diff --git a/twake/frontend/src/app/components/on-boarding/popups/blocked-company.tsx b/twake/frontend/src/app/components/on-boarding/popups/blocked-company.tsx new file mode 100644 index 0000000000..a3c1e65329 --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/popups/blocked-company.tsx @@ -0,0 +1,138 @@ +import React from 'react'; +import { Button, Row, Typography, Select } from 'antd'; +import ObjectModal from '../../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import LoginService from 'app/features/auth/login-service'; +import { CompanyType } from 'app/features/companies/types/company'; +import { capitalize } from 'lodash'; +import ModalManager from 'app/components/modal/modal-manager'; +import UserService from 'app/features/users/services/current-user-service'; +import Groups from 'app/deprecated/workspaces/groups.js'; +import { AlertTriangle } from 'react-feather'; +import consoleService from 'app/features/console/services/console-service'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; + +type SwitchCompanyPropsType = { + placeholder?: string; + companiesIds: string[]; +}; + +const { Option } = Select; +const { Text, Title } = Typography; +const SwitchCompany = ({ placeholder, companiesIds }: SwitchCompanyPropsType): JSX.Element => { + const userGroups: { [key: string]: CompanyType } = Groups.user_groups; + const companies = companiesIds + .map(id => userGroups[id]) + .filter(company => company.plan?.billing?.status !== 'error'); + + const onSelect = (companyId: string) => { + Groups.select(userGroups[companyId]); + return ModalManager.close(); + }; + + const onClickBtn = () => LoginService.logout(); + + return ( + (!!companies.length && ( + <Select + placeholder={placeholder || 'Select a company'} + onSelect={onSelect} + style={{ width: 224 }} + > + {companies.map(company => ( + <Option key={company.id} value={company.id}> + {capitalize(company.name)} + </Option> + ))} + </Select> + )) || ( + <Button + type="primary" + style={{ height: 36, width: 163, backgroundColor: 'var(--red)' }} + onClick={onClickBtn} + > + {Languages.t('scenes.app.channelsbar.currentuser.logout')} + </Button> + ) + ); +}; + +export default (): JSX.Element => { + const companyId = useRouterCompany(); + const onClickButton = () => + window.open( + consoleService.getCompanySubscriptionUrl(companyId), + 'blank', + ); + + return ( + <ObjectModal + title={ + <div style={{ display: 'flex' }}> + <AlertTriangle size={24} /> + <span className="small-left-margin"> + {Languages.t('components.on_boarding.popups.blocked_company.title')} + </span> + </div> + } + titleColor="var(--white)" + titleCenter + headerStyle={{ backgroundColor: 'var(--red)', color: 'var(--white)', height: 76 }} + hideFooterDivider + footerAlign="center" + footerStyle={{ marginBottom: 24 }} + footer={ + <Row justify="space-between" align="middle"> + <div + style={{ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + marginTop: 32, + }} + > + <Button type="ghost" size="large" onClick={onClickButton}> + {Languages.t( + 'components.on_boarding.popups.blocked_company.company_subscription_plan_button', + )} + </Button> + <Text style={{ margin: '8px 0 ' }} strong> + {Languages.t('components.on_boarding.popups.blocked_company.or')} + </Text> + <SwitchCompany + placeholder={Languages.t( + 'components.on_boarding.popups.blocked_company.company_selector', + )} + companiesIds={[...(UserService.getCurrentUser()?.groups_id || [])]} + /> + </div> + </Row> + } + > + <Row justify="center" style={{ marginTop: 36 }}> + <Title + level={3} + style={{ + textAlign: 'center', + margin: 0, + width: 493, + }} + > + {Languages.t('components.on_boarding.popups.blocked_company.description')} + + + + + + {Languages.t('components.on_boarding.popups.blocked_company.learn_more_text')} + + + + ); +}; diff --git a/twake/frontend/src/app/components/on-boarding/popups/unverified-account.tsx b/twake/frontend/src/app/components/on-boarding/popups/unverified-account.tsx new file mode 100644 index 0000000000..2f7186efbb --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/popups/unverified-account.tsx @@ -0,0 +1,86 @@ +import React, { useState } from 'react'; +import { Button, Row, Typography } from 'antd'; +import ObjectModal from '../../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import ConsoleService from 'app/features/console/services/console-service'; + +type PropsType = { + daysLeft: number; + limit: number; + email: string; +}; + +export default ({ daysLeft, email, limit }: PropsType): JSX.Element => { + const [loading, setLoading] = useState(false); + + const onClickButton = () => { + setLoading(true); + return ConsoleService.verifyMail().finally(() => setLoading(false)); + }; + + return ( + + {Languages.t('general.re_send')} + + } + > + + + {Languages.t('components.unverified_account.typography_text_danger', [daysLeft, limit])} + + + + + + {Languages.t('components.unverified_account.verification_details')} + + + + + + {email} + + + + + + {Languages.t('components.unverified_account.re_send_email')} + + + + ); +}; diff --git a/twake/frontend/src/app/components/on-boarding/popups/welcome-on-twake.tsx b/twake/frontend/src/app/components/on-boarding/popups/welcome-on-twake.tsx new file mode 100644 index 0000000000..2413dff260 --- /dev/null +++ b/twake/frontend/src/app/components/on-boarding/popups/welcome-on-twake.tsx @@ -0,0 +1,119 @@ +import { Button, Row, Typography } from 'antd'; +import React, { useState } from 'react'; +import Emojione from '../../emojione/emojione'; +import ObjectModal from '../../object-modal/object-modal'; +import Languages from 'app/features/global/services/languages-service'; +import ModalManager from 'app/components/modal/modal-manager'; +import AddMailsInWorkspace from './add-mails-in-workspace'; +import ConsoleService from 'app/features/console/services/console-service'; + +type PropsType = { + email: string; +}; + +export default ({ email }: PropsType) => { + const [loading, setLoading] = useState(false); + const openAddMembers = () => + ModalManager.open(, { + position: 'center', + size: { width: '600px' }, + }); + + const onClickButton = () => { + setLoading(true); + return ConsoleService.verifyMail().finally(() => setLoading(false)); + }; + + return ( + + {Languages.t('components.verify_mail.title_1')} + +
+ } + closable + style={{ height: 600 }} + titleLevel={2} + titleCenter + footerAlign="center" + hideFooterDivider + footer={ + + } + > + + + {Languages.t('components.verify_mail.title_2')} + + + + + {Languages.t('components.verify_mail.text')} + + + + + + {email} + + + + + + {Languages.t('components.verify_mail.paragraph')} + + + + + + {Languages.t('components.unverified_account.re_send_email')} + + + + + + + + ); +}; diff --git a/twake/frontend/src/app/components/OnlineUserStatus/OnlineUserStatus.scss b/twake/frontend/src/app/components/online-user-status/online-user-status.scss similarity index 100% rename from twake/frontend/src/app/components/OnlineUserStatus/OnlineUserStatus.scss rename to twake/frontend/src/app/components/online-user-status/online-user-status.scss diff --git a/twake/frontend/src/app/components/online-user-status/online-user-status.tsx b/twake/frontend/src/app/components/online-user-status/online-user-status.tsx new file mode 100644 index 0000000000..6447ffb0cd --- /dev/null +++ b/twake/frontend/src/app/components/online-user-status/online-user-status.tsx @@ -0,0 +1,47 @@ +// eslint-disable-next-line @typescript-eslint/no-use-before-define +import React, { Suspense } from 'react'; +import classNames from 'classnames'; + +import { UserType } from 'app/features/users/types/user'; +import { useOnlineUser } from 'app/features/users/hooks/use-online-user'; + +import './online-user-status.scss'; +import { useUser } from 'app/features/users/hooks/use-user'; + +type PropsType = { + user: UserType; + size?: 'small' | 'medium' | 'big'; +}; + +const WrappedUserStatus = ({ user: _user, size = 'medium' }: PropsType): JSX.Element => { + const user = useUser(_user.id || ''); + const userOnlineStatus = useOnlineUser(_user.id as string); + //const lastSeen = userOnlineStatus?.lastSeen || user.last_seen; + const online = + (userOnlineStatus && userOnlineStatus.connected) || + (!userOnlineStatus?.lastSeen && + user?.is_connected && + (user?.last_seen || 0) > Date.now() - 10 * 60 * 1000); + + return ( +
+ ); +}; + +const UserOnlineStatus = (props: PropsType): JSX.Element => { + return ( + }> + + + ); +}; + +export default UserOnlineStatus; diff --git a/twake/frontend/src/app/components/open-desktop-popup/open-desktop-popup.tsx b/twake/frontend/src/app/components/open-desktop-popup/open-desktop-popup.tsx new file mode 100644 index 0000000000..a5a25f5160 --- /dev/null +++ b/twake/frontend/src/app/components/open-desktop-popup/open-desktop-popup.tsx @@ -0,0 +1,39 @@ +import React, { useState, useEffect } from 'react'; +import { Logo } from 'app/atoms/logo'; +import { Subtitle } from 'app/atoms/text'; +import A from 'app/atoms/link'; +import { useRecoilState } from 'recoil'; +import { useWebState } from 'app/features/global/state/atoms/use-web'; +import Languages from 'app/features/global/services/languages-service'; + +export const OpenDesktopPopup = (): React.ReactElement => { + const [showLink, setShowLink] = useState(true); + const [, setUseWeb] = useRecoilState(useWebState); + + useEffect(() => { + setTimeout(() => { + setShowLink(true); + }, 5000); + }, []); + + return ( +
+ + + {Languages.t('components.open_desktop_popup.subtitle')} + + {showLink && ( + <> + { + setUseWeb(true); + }} + > + {Languages.t('components.open_desktop_popup.open_here_link')} + + + )} +
+ ); +}; diff --git a/twake/frontend/src/app/components/parameters/attribute.js b/twake/frontend/src/app/components/parameters/attribute.js new file mode 100755 index 0000000000..3bbe597c3d --- /dev/null +++ b/twake/frontend/src/app/components/parameters/attribute.js @@ -0,0 +1,87 @@ +import React, { Component } from 'react'; + +import Number from 'app/features/global/utils/Numbers'; +import AttributesManager from './attributes-manager.js'; +import './parameters.scss'; +import Languages from 'app/features/global/services/languages-service'; + +export default class Attribute extends React.Component { + constructor(props) { + super(); + + this.id = Number.unid(); + + this.state = { + parameters_attributes: AttributesManager, + i18n: Languages, + }; + + this.timeout = setTimeout(''); + + Languages.addListener(this); + AttributesManager.addListener(this); + } + componentDidMount() { + if (this.props.autoOpen) { + AttributesManager.toggle(this.id); + } + } + componentWillUnmount() { + clearTimeout(this.timeout); + Languages.removeListener(this); + AttributesManager.removeListener(this); + } + componentDidUpdate() { + var open = this.state.parameters_attributes.open == this.id; + if (open && !this.was_open) { + this.value_node.style.maxHeight = 'none'; + this.value_height = window.getBoundingClientRect(this.value_node).height; + this.value_node.style.maxHeight = '0px'; + clearTimeout(this.timeout); + this.timeout = setTimeout(() => { + this.value_node.style.maxHeight = this.value_height + 'px'; + + this.timeout = setTimeout(() => { + this.value_node.style.maxHeight = 'none'; + this.value_height = window.getBoundingClientRect(this.value_node).height; + }, 200); + }, 50); + + if (this.props.focusOnOpen) { + this.props.focusOnOpen.focus(); + } + } else if (!open && this.was_open) { + clearTimeout(this.timeout); + + this.value_node.style.maxHeight = this.value_height + 'px'; + this.timeout = setTimeout(() => { + this.value_node.style.maxHeight = '0px'; + }, 50); + } + this.was_open = open; + } + render() { + return ( +
+
AttributesManager.toggle(this.id)}> + {!this.props.autoOpen && ( + + {this.state.parameters_attributes.open == this.id + ? this.state.i18n.t('general.close') + : this.state.i18n.t('general.open')} + + )} +
{this.props.label}
+
{this.props.description}
+
+
(this.value_node = node)} className="value"> + {this.props.children} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/parameters/attributes-manager.js b/twake/frontend/src/app/components/parameters/attributes-manager.js new file mode 100755 index 0000000000..76886190b1 --- /dev/null +++ b/twake/frontend/src/app/components/parameters/attributes-manager.js @@ -0,0 +1,26 @@ +import React, { Component } from 'react'; + +import Observable from 'app/deprecated/CollectionsV1/observable.js'; + +/* + Menus manager service, choose where to generate menu +*/ +class AttributesManager extends Observable { + constructor() { + super(); + this.setObservableName('parameters_attributes'); + + this.open = ''; + } + toggle(id) { + if (this.open == id) { + this.open = ''; + } else { + this.open = id; + } + this.notify(); + } +} + +const service = new AttributesManager(); +export default service; diff --git a/twake/frontend/src/app/components/Parameters/Parameters.scss b/twake/frontend/src/app/components/parameters/parameters.scss similarity index 100% rename from twake/frontend/src/app/components/Parameters/Parameters.scss rename to twake/frontend/src/app/components/parameters/parameters.scss diff --git a/twake/frontend/src/app/components/picker/picker.js b/twake/frontend/src/app/components/picker/picker.js new file mode 100755 index 0000000000..d7bd11551f --- /dev/null +++ b/twake/frontend/src/app/components/picker/picker.js @@ -0,0 +1,261 @@ +import React, { Component } from 'react'; +import AutoComplete from 'components/auto-complete/auto-complete'; +import Icon from 'components/icon/icon.js'; +import Languages from 'app/features/global/services/languages-service'; +import './picker.scss'; + +export default class Picker extends React.Component { + /* + placeholder : string, + search : Array of search function, + renderItem(item) : how to render item + renderItemChoosen(item) : how to add item in input + renderItemSimply(item) : what user will type on input and what we have to replace + onChangeSuggested(list) + onChange(list) : + canCreate + onCreate + disableNavigationKey : + */ + constructor(props) { + super(props); + this.state = { + currentSelected: props.value || [], + inputValue: '', + currentList: [], + selected: [], + }; + this.alreadyBackspace = false; + } + componentWillUnmount() { + document.removeEventListener('click', this.outsideClickListener); + } + componentDidMount() { + if (!this.props.inline) { + this.focus(); + } + + var element = this.container; + this.outsideClickListener = event => { + if (!element.contains(event.target) && document.contains(event.target)) { + this.setState({ focused: false }); + } + }; + this.outsideClickListener = this.outsideClickListener.bind(this); + document.addEventListener('click', this.outsideClickListener); + } + componentWillUpdate(nextProps, nextState) { + if (nextProps.value != this.props.value) { + nextState.currentSelected = nextProps.value; + } + return true; + } + onSelect(item) { + this.alreadyBackspace = true; + if (item && (item.id === undefined || item.id < 0) && item.front_id === undefined) { + this.onCreate(item.textSearched); + return; + } + var newList = this.state.currentSelected; + for (var i = 0; i < newList.length; i++) { + if (newList[i].id == item.id) { + this.setState({ inputValue: '' }); + return false; + } + } + newList.push(item); + this.setState({ currentSelected: newList }); + this.setState({ inputValue: '' }); + if (this.props.onChange) { + this.props.onChange(newList); + } + this.focus(); + } + onRemove(item) { + var newList = this.state.currentSelected; + var index = newList.indexOf(item); + if (index >= 0) { + newList.splice(index, 1); + this.setState({ currentSelected: newList }); + if (this.props.onChange) { + this.props.onChange(newList); + } + } + this.focus(); + } + onBackspace() { + if (this.alreadyBackspace) { + // if already typed on backspace once + var newList = this.state.currentSelected; + newList.splice(newList.length - 1, 1); + this.setState({ currentSelected: newList }); + } else { + this.alreadyBackspace = true; + } + } + onCreate(text) { + if (this.props.onCreate) { + var item = this.props.onCreate(text, item => { + this.onSelect(item); + }); + } + } + focus() { + if (this.autocomplete_node) { + this.autocomplete_node.focus(); + } + } + render() { + var that = this; + var objects = [ +
+
+ {this.state.currentSelected.map(item => { + return this.props.renderItemChoosen(item); + })} + {!this.props.readOnly && ( + { + var text = this.state.inputValue; + this.props.search(text, list => { + if (that.props.canCreate && text.length > 0) { + list.push({ id: -1, autocomplete_id: list.length, textSearched: text }); + } + cb(list); + }); + }, + ]} + renderItemChoosen={[ + item => { + if (item.id < 0 && this.props.canCreate) { + return item.textSearched; + } else { + return this.props.renderItemSimply(item); + } + }, + ]} + max={[this.props.max || 10]} + renderItem={[() => {}]} + regexHooked={[/(.*)/]} + placeholder={ + this.state.currentSelected.length + ? '' + : this.props.placeholder || + Languages.t('scenes.apps.drive.left.search', [], 'Search') + } + onChange={evt => { + this.alreadyBackspace = false; + this.setState({ inputValue: evt.target.value }); + }} + onSelect={item => { + this.onSelect(item); + }} + value={this.state.inputValue} + onChangeCurrentList={(list, selected) => { + this.setState({ currentList: list, selected: selected }); + if (this.props.onChangeSuggested) { + this.props.onChangeSuggested(list); + } + }} + hideResult={true} + onBackspace={() => { + this.onBackspace(); + }} + disableNavigationKey={this.props.disableNavigationKey} + showResultsOnInit={true} + onHide={() => this.setState({ focused: false })} + ref={node => { + this.autocomplete_node = node; + }} + /> + )} +
+
, + ]; + + if (!this.props.readOnly) { + if (!this.props.inline) { + objects.push(
{!!this.props.title && this.props.title}
); + } + + var results = []; + + if (this.state.currentList.length > 0) { + results = this.state.currentList.map((item, index) => { + if (item.id < 0) { + return ( +
{ + evt.stopPropagation(); + evt.preventDefault(); + this.onSelect(item); + }} + > +
+ + Create {this.props.renderItem(item.textSearched)} +
+
+ ); + } else { + return ( +
{ + evt.stopPropagation(); + evt.preventDefault(); + this.onSelect(item); + }} + > +
{this.props.renderItem(item)}
+
+ ); + } + }); + } + if (this.props.inline) { + results = ( +
+ {results} +
+ ); + } + objects = objects.concat(results); + } + + objects = ( +
{ + this.focus(); + this.setState({ focused: true }); + }} + ref={node => (this.container = node)} + className={ + 'picker_container ' + + (this.props.readOnly ? 'readOnly ' : '') + + (this.props.inline ? 'inline ' : '') + + (this.state.focused ? 'focused ' : '') + + this.props.className + } + > + {objects} +
+ ); + + return objects; + } +} diff --git a/twake/frontend/src/app/components/Picker/Picker.scss b/twake/frontend/src/app/components/picker/picker.scss similarity index 100% rename from twake/frontend/src/app/components/Picker/Picker.scss rename to twake/frontend/src/app/components/picker/picker.scss diff --git a/twake/frontend/src/app/components/popup-component/popup-component.js b/twake/frontend/src/app/components/popup-component/popup-component.js new file mode 100755 index 0000000000..8e80b718ff --- /dev/null +++ b/twake/frontend/src/app/components/popup-component/popup-component.js @@ -0,0 +1,42 @@ +import React, { Component } from 'react'; +import './popup-component.scss'; +import popupManager from 'app/deprecated/popupManager/popupManager.js'; +import CloseIcon from '@material-ui/icons/CloseOutlined'; + +export default class PopupComponent extends React.Component { + constructor(props) { + super(props); + this.state = { + popupManager: popupManager, + }; + popupManager.addListener(this); + } + componentWillUnmount() { + popupManager.removeListener(this); + document.removeEventListener('keydown', this.eventClose); + } + componentDidMount() { + document.addEventListener('keydown', this.eventClose); + } + eventClose(evt) { + if (evt.keyCode == 27 && popupManager.canClose()) { + popupManager.close(); + } + } + render() { + return ( +
+ {this.state.popupManager.canClose() && ( +
+
this.state.popupManager.close()}> + +
+
+ )} +
+
{this.state.popupManager.getComponent()}
+
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/popup-component/popup-component.scss b/twake/frontend/src/app/components/popup-component/popup-component.scss new file mode 100755 index 0000000000..cdda6b8a9a --- /dev/null +++ b/twake/frontend/src/app/components/popup-component/popup-component.scss @@ -0,0 +1,104 @@ +.popupComponent { + height: 100%; + width: 100%; + background: white; + + position: absolute; + z-index: 100; + width: 90vw; + height: 90vh; + transform: translate(-50%, -50%); + top: 50%; + left: 50%; + box-shadow: 0 0 0px 1000px #00000088; + border-radius: 16px; + overflow: hidden; + + display: flex; + + @media (max-width: 800px) { + border-radius: 0px; + width: 100vw; + height: 100vh; + max-height: -webkit-fill-available; + } + + .header { + .close { + background: #f2f2f2; + border-radius: 50%; + width: 44px; + height: 44px; + line-height: 40px; + padding: 8px; + box-sizing: border-box; + position: absolute; + right: 24px; + top: 24px; + border: 4px solid #fff; + cursor: pointer; + z-index: 10; + line-height: normal; + + &:hover { + background: #eee; + & > * { + opacity: 0.8; + } + } + & > * { + opacity: 0.5; + } + } + } + + .componentContainer { + flex: 1; + overflow: hidden; + position: relative; + + .component { + overflow: hidden; + height: 100%; + + & > div { + overflow: hidden; + height: 100%; + } + + .main { + display: flex; + width: 100%; + height: 100%; + position: relative; + box-sizing: border-box; + + .sideBar { + width: 220px; + padding-top: 32px; + margin-left: 15px; + } + + .content { + padding-top: 32px; + max-height: 100%; + } + } + } + } + + @media only screen and (max-width: 600px) { + .header { + .close { + right: auto; + left: 16px; + } + } + .main .content { + margin-left: 0px !important; + } + .main .sideBar { + display: none; + } + } +} diff --git a/twake/frontend/src/app/components/quoted-message/quoted-message.tsx b/twake/frontend/src/app/components/quoted-message/quoted-message.tsx new file mode 100644 index 0000000000..2bdc7d86f7 --- /dev/null +++ b/twake/frontend/src/app/components/quoted-message/quoted-message.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { useMessage } from 'app/features/messages/hooks/use-message'; +import useRouterCompany from 'app/features/router/hooks/use-router-company'; +import MessageQuote from 'app/molecules/message-quote'; +import { useUser } from 'app/features/users/hooks/use-user'; +import { useMessageQuoteReply } from 'app/features/messages/hooks/use-message-quote-reply'; +import useRouterChannel from 'app/features/router/hooks/use-router-channel'; +import User from 'app/features/users/services/current-user-service'; +import { gotoMessage } from 'src/utils/messages'; +import useRouterWorkspace from 'app/features/router/hooks/use-router-workspace'; +import QuotedContent from 'app/molecules/quoted-content'; + +type PropsType = { + closable?: boolean; + onClose?: () => void; +}; + +export default ({ closable = true, onClose }: PropsType): React.ReactElement => { + const companyId = useRouterCompany(); + const channelId = useRouterChannel(); + const workspaceId = useRouterWorkspace(); + const { message: quotedMessageId } = useMessageQuoteReply(channelId); + const quotedMessage = useMessage({ + companyId, + threadId: quotedMessageId, + id: quotedMessageId, + }); + + if (!quotedMessage.message) { + return <>; + } + + const { message } = quotedMessage; + const author = useUser(message.user_id); + const authorName = author ? User.getFullName(author) : 'Anonymous'; + const deleted = message.subtype === 'deleted'; + const quotedContent = ; + + return ( + gotoMessage(message, companyId, channelId, workspaceId)} + /> + ); +}; diff --git a/twake/frontend/src/app/components/reminder-selector/reminder-selector.js b/twake/frontend/src/app/components/reminder-selector/reminder-selector.js new file mode 100755 index 0000000000..e886e8b53f --- /dev/null +++ b/twake/frontend/src/app/components/reminder-selector/reminder-selector.js @@ -0,0 +1,198 @@ +import React, { Component } from 'react'; +import Button from 'components/buttons/button.js'; +import Input from 'components/inputs/input.js'; +import Icon from 'components/icon/icon.js'; +import Select from 'components/select/select.js'; +import './reminder-selector.scss'; +import Languages from 'app/features/global/services/languages-service'; + +export default class ReminderSelector extends React.Component { + constructor(props) { + super(props); + + this.state = { + reminders: [], + }; + + this.old_value = JSON.stringify(props.reminders || []); + } + + componentDidMount() { + this.updateFromProps(this.props); + } + + shouldComponentUpdate(nextProps, nextState) { + if (this.old_value != JSON.stringify(nextProps.reminders)) { + this.old_value = JSON.stringify(nextProps.reminders); + this.updateFromProps(nextProps); + } + return true; + } + + remove(i) { + delete this.state.reminders[i]; + this.update(); + } + + add() { + this.state.reminders.push({ + mode: 'push', + delay_unit: 'minutes', + delay_value: '30', + }); + this.update(); + } + + update() { + var ret = []; + this.state.reminders.forEach(item => { + if (item.delay_unit == 'minutes' && item.delay_value > 59) { + item.delay_value = 30; + } + if (item.delay_unit == 'hours' && item.delay_value > 23) { + item.delay_value = 1; + } + if (item.delay_unit == 'days' && item.delay_value > 13) { + item.delay_value = 1; + } + if (item.delay_unit == 'weeks' && item.delay_value < 2) { + item.delay_value = 2; + } + + ret.push({ + mode: item.mode, + delay: + parseInt(item.delay_value) * + 60 * + (item.delay_unit == 'hours' ? 60 : 1) * + (item.delay_unit == 'days' ? 60 * 24 : 1) * + (item.delay_unit == 'weeks' ? 60 * 24 * 7 : 1), + }); + }); + + if (this.props.onChange) { + this.props.onChange(ret); + } + + this.setState({}); + } + + updateFromProps(nextProps) { + var props = nextProps || this.props; + + var reminders = []; + + (props.reminders || []).forEach(item => { + var delay_value = parseInt(item.delay / 60); + var delay_unit = 'minutes'; + if (item.delay > 59 * 60) { + delay_value = parseInt(item.delay / (60 * 60)); + delay_unit = 'hours'; + } + if (item.delay > 23 * 60 * 60) { + delay_value = parseInt(item.delay / (60 * 60 * 24)); + delay_unit = 'days'; + } + if (item.delay > 13 * 24 * 60 * 60) { + delay_value = parseInt(item.delay / (60 * 60 * 24 * 7)); + delay_unit = 'weeks'; + } + reminders.push({ + mode: item.mode, + delay_value: delay_value, + delay_unit: delay_unit, + }); + }); + + this.setState({ reminders: reminders }); + } + + render() { + return ( +
+ {this.state.reminders.map((reminder, i) => { + return ( +
+ { + this.state.reminders[i].delay_value = evt.target.value; + if (!evt.target.value) { + return; + } + this.update(); + }} + style={{ width: 60 }} + /> + + setInput({ ...input, query: e.target.value })} + value={input.query} + className={className + ' rounded-tr-none rounded-br-none'} + placeholder={Languages.t('scenes.app.mainview.quick_search_placeholder')} + /> + )} + /> + +
+ ); +}; diff --git a/twake/frontend/src/app/components/search-popup/search-popup.scss b/twake/frontend/src/app/components/search-popup/search-popup.scss new file mode 100755 index 0000000000..27169056ae --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/search-popup.scss @@ -0,0 +1,516 @@ +//@import url("https://fonts.googleapis.com/css?family=Inter:400,500,600,700"); + +:root { + --white: #fff; + --border-radius-base: 8px; + + --accentlight: #007aff; + --backgroundlight: #ffffff; + --iconlight: #818c99; + --messagebubblelight: #ebedf0; + --separatorlight: #d7d8d9; + --textprimary: #ffffff; + --textprimarylight: #000000; + --texttertiarylight: #818c99; + + --font-size-l: 15px; + --font-size-m: 14px; + --font-size-s: 13px; + --font-size-xl: 16px; + --font-size-xxl: 17px; + --font-size-xxxl: 21px; + --font-size-xxxxl: 24px; + + --font-weight-regular: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + --font-family-inter: 'Inter', Helvetica; +} + +.screen input:focus { + outline: none; +} + +.screen * { + -webkit-font-smoothing: antialiased; + box-sizing: border-box; +} + +.screen div { + -webkit-text-size-adjust: none; +} + +.container-center-horizontal { + display: flex; + flex-direction: row; + justify-content: center; + pointer-events: none; + width: 100%; +} + +.container-center-horizontal > * { + flex-shrink: 0; + pointer-events: auto; +} + +@keyframes reveal { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +input:focus { + outline: none; +} + +* { + box-sizing: border-box; +} + +/* screen - search */ + +.search-popup .overlay { + position: absolute; + z-index: 8; + left: 0; + top: 0; + width: 100%; + height: 100%; + background: #0000002e; +} + +.search-popup .component-container { + position: absolute; + margin: auto; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 0px; + height: 0px; + z-index: 9; + //transition: opacity 1s easy-out, top 0.2s, bottom 0.2s, left 0.2s, right 0.2s; + margin-top: 30vh; +} + +.search-popup { + .searchLoading { + text-align: center; + } +} + +.search { + justify-content: flex-start; + mix-blend-mode: normal; + + //position: absolute; + height: calc(100vh - 20px); + transform: translate(-50%, -29%); + background: var(--white); + box-shadow: 0 2px 32px rgba(0, 0, 0, 0.2); + + .tabs-wrapper { + width: 100%; + align-items: flex-start; + display: flex; + flex-direction: column; + justify-content: flex-start; + mix-blend-mode: normal; + //position: absolute; + //top: 112px; + .tab-items-wrapper { + align-items: flex-start; + display: flex; + justify-content: flex-start; + overflow: hidden; + + .tab-item-wrapper { + align-items: center; + display: flex; + height: 48px; + justify-content: flex-start; + min-width: 73px; + padding-left: 16px; + padding-right: 16px; + z-index: 1; + + .tab-item-active { + border-bottom: 2px solid var(--accentlight); + } + + .tab-item-title { + color: var(--iconlight); + font-family: var(--font-family-inter); + font-size: var(--font-size-xl); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: -0.16px; + line-height: 20px; + mix-blend-mode: normal; + position: relative; + text-align: center; + white-space: nowrap; + width: auto; + padding: 0px 10px; + } + + .tab-item-active .tab-item-title { + color: var(--accentlight); + } + + .tab-item-indicator { + align-self: stretch; + + height: 6.5px; + position: relative; + } + } + } + + .tab-horizontal-separator { + height: 1px; + background-color: var(--separatorlight); + mix-blend-mode: normal; + width: calc(100% - 30px); + margin: 0px 15px; + margin-top: -11px; + } + } + + .input-wrapper { + position: relative; + width: 100%; + padding: 0 12px; + + .input.big { + height: 36px; + background-color: var(--messagebubblelight); + padding-left: 36px; + font-weight: var(--font-weight-regular); + } + + .input_icon.big > i { + padding-top: 6px; + padding-left: 8px; + font-size: 16px; + } + + .input-clear-btn { + position: absolute; + top: 10px; + right: 24px; + cursor: pointer; + } + } + + .header-wrapper { + width: 100%; + min-height: 52px; + position: relative; + } + + .header-title { + margin: 0 auto; + padding-top: 16px; + color: var(--textprimarylight); + font-family: var(--font-family-inter); + font-size: var(--font-size-xxxl); + font-style: normal; + font-weight: 700; + letter-spacing: 0px; + line-height: 26px; + mix-blend-mode: normal; + position: relative; + text-align: center; + white-space: nowrap; + width: 100%; + } + + .header-close-btn { + border-radius: 10px; + height: 25px; + top: 17px; + right: 12px; + position: absolute; + width: 25px; + cursor: pointer; + } + + .results-wrapper { + //* {box-shadow: 0 0 0 1px gray;} + + overflow: hidden; + margin-top: 4px; + margin-left: 18px; + width: calc(100% - 36px); + + .results-group { + margin-bottom: 15px; + } + + .results-group:last-child { + margin-bottom: 0; + } + + .results-group-title { + margin-bottom: 10px; + letter-spacing: -0.15px; + line-height: 18px; + mix-blend-mode: normal; + text-align: left; + white-space: nowrap; + color: var(--textprimarylight); + font-family: var(--font-family-inter); + font-size: var(--font-size-l); + font-style: normal; + font-weight: var(--font-weight-semibold); + } + } + + .search-results { + .result-items { + margin-top: 10px; + margin-bottom: 20px; + + .result-item { + display: flex; + margin-bottom: 15px; + cursor: pointer; + + .component-channel-avatar .channel-icon-wrapper { + width: 60px; + height: 60px; + } + + .result-item-icon { + height: 58px; + width: 58px; + position: relative; + } + + .result-item-content { + margin-left: 10px; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + flex: 1 1 auto; + -webkit-mask-image: linear-gradient(to right, black 85%, transparent 100%); + mask-image: linear-gradient(to right, black 85%, transparent 100%); + overflow: hidden; + + .channel-title { + letter-spacing: -0.41px; + line-height: 22px; + mix-blend-mode: normal; + text-align: left; + white-space: nowrap; + color: var(--textprimarylight); + font-family: var(--font-family-inter); + font-size: var(--font-size-xxl); + font-style: normal; + font-weight: var(--font-weight-semibold); + margin-bottom: 1px; + } + + .channel-description { + color: #6d7885; + font-family: var(--font-family-inter); + font-size: var(--font-size-l); + font-style: normal; + font-weight: var(--font-weight-regular); + height: 16px; + letter-spacing: -0.24px; + line-height: 20px; + mix-blend-mode: normal; + text-align: left; + white-space: nowrap; + margin-bottom: 5px; + } + + .messages-title { + font-family: var(--font-family-inter); + font-style: normal; + font-weight: 600; + font-size: 15px; + line-height: 16px; + display: flex; + align-items: center; + text-align: center; + letter-spacing: -0.352941px; + } + + .messages-author { + color: var(--textprimarylight); + font-family: var(--font-family-inter); + font-size: var(--font-size-m); + font-style: normal; + font-weight: var(--font-weight-regular); + + letter-spacing: -0.15px; + line-height: 18px; + mix-blend-mode: normal; + text-align: center; + white-space: nowrap; + } + + .messages-text { + font-style: normal; + letter-spacing: -0.02px; + color: var(--iconlight); + font-family: var(--font-family-inter); + font-size: var(--font-size-m); + font-weight: var(--font-weight-regular); + line-height: 16px; + margin-bottom: 2px; + } + + .highlight { + color: var(--accentlight); + } + + .messages-text .highlight { + color: var(--accentlight); + font-family: var(--font-family-inter); + font-style: normal; + font-weight: var(--font-weight-medium); + letter-spacing: -0.02px; + } + } + + .result-item-postfix { + color: #b8c1cc; + font-family: var(--font-family-inter); + font-size: var(--font-size-s); + font-style: normal; + font-weight: var(--font-weight-medium); + height: auto; + letter-spacing: -0.14px; + line-height: 20px; + mix-blend-mode: normal; + text-align: right; + white-space: nowrap; + width: auto; + } + + .result-item-icon { + .result-item-icon-title { + line-height: 38pt; + font-size: 46pt; + } + + .result-item-icon-back { + height: 56px; + mix-blend-mode: normal; + position: absolute; + width: 56px; + visibility: visible; + border-radius: 50%; + background-size: cover; + background-position: center; + } + } + + //.result-item-channel-icon { + // .result-item-icon-title { + // line-height: 44pt; + // font-size: 20pt; + // padding-left: 16px; + // } + //} + } + } + } + + .search-results { + .result-items-channel { + padding: 4px; + display: flex; + flex-direction: row; + height: 110px; + border-bottom: 0.5px solid #ddd; + + -webkit-mask-image: linear-gradient(to right, black 92%, transparent 100%); + mask-image: linear-gradient(to right, black 92%, transparent 100%); + + .result-item { + margin-right: 4px; + cursor: pointer; + } + + .component-channel-avatar { + .channel-icon-wrapper { + transition: transform 0.15s; + } + } + + .component-channel-avatar:hover { + .channel-icon-wrapper { + transform: scale(1.1); + } + } + } + + .result-items-files { + display: flex; + flex-direction: column; + max-height: 520px; + + .result-item { + display: flex; + flex-direction: row; + margin-bottom: 10px; + padding-bottom: 5px; + border-bottom: 0.5px solid #ddd; + + .result-item-icon { + } + .result-item-info { + width: 100%; + margin-left: 10px; + .filename { + font-weight: 400; + font-size: 15px; + line-height: 20px; + letter-spacing: -0.272px; + color: #000000; + } + .details { + font-style: normal; + font-weight: 400; + font-size: 11px; + line-height: 14px; + letter-spacing: -0.192px; + color: #6d7885; + } + .sender { + margin-top: 2px; + font-style: normal; + font-weight: 400; + font-size: 12px; + line-height: 20px; + letter-spacing: -0.24px; + } + } + } + } + } + + .recent-results.tab-all { + .result-items-files { + max-height: 206px; + } + } + + .recent-results.tab-media { + .result-items-media { + flex-flow: row wrap; + height: 508px; + } + } +} diff --git a/twake/frontend/src/app/components/search-popup/search-popup.tsx b/twake/frontend/src/app/components/search-popup/search-popup.tsx new file mode 100755 index 0000000000..54fdc23ef9 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/search-popup.tsx @@ -0,0 +1,24 @@ +import { Modal, ModalContent } from '@atoms/modal'; +import Languages from 'app/features/global/services/languages-service'; +import { useSearchModal } from 'app/features/search/hooks/use-search'; +import { SearchInput } from './search-input'; +import { SearchResultsIndex } from './search-tabs'; + +export default () => { + const { open, setOpen } = useSearchModal(); + + return ( + setOpen(false)} className="sm:w-[80vw] sm:max-w-4xl"> + + + ); +}; + +const SearchBox = () => { + return ( + + + + + ); +}; diff --git a/twake/frontend/src/app/components/search-popup/search-tabs.tsx b/twake/frontend/src/app/components/search-popup/search-tabs.tsx new file mode 100755 index 0000000000..21c3655450 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/search-tabs.tsx @@ -0,0 +1,100 @@ +import Tabs from '@molecules/tabs'; +import Languages from 'app/features/global/services/languages-service'; +import { useSearchChannels } from 'app/features/search/hooks/use-search-channels'; +import { + useSearchMessagesFiles, + useSearchMessagesMedias, +} from 'app/features/search/hooks/use-search-files-or-medias'; +import { useSearchMessages } from 'app/features/search/hooks/use-search-messages'; +import { SearchInputState, SearchTabsState } from 'app/features/search/state/search-input'; +import PerfectScrollbar from 'react-perfect-scrollbar'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import SearchResultsAll from './tabs/all'; +import SearchResultsChannels from './tabs/channels'; +import SearchResultsFiles from './tabs/files'; +import SearchResultsMedias from './tabs/medias'; +import SearchResultsMessages from './tabs/messages'; + +const orderedTabs = ['all', 'messages', 'medias', 'files', 'channels']; + +export const SearchResultsIndex = () => { + const input = useRecoilValue(SearchInputState); + const hasInput = input?.query?.length > 0; + const [tab, setTab] = useRecoilState(SearchTabsState); + + const { messages } = useSearchMessages(); + const { files } = useSearchMessagesFiles(); + const { files: medias } = useSearchMessagesMedias(); + + return ( + <> + {Languages.t('components.searchpopup.all')}
, +
+
+ {Languages.t('components.searchpopup.messages')} + {hasInput && } +
+
, +
+
+ {Languages.t('components.searchpopup.media')} + {hasInput && } +
+
, +
+
+ {Languages.t('components.searchpopup.files')} + {hasInput && } +
+
, + .../*!input.channelId + ?*/ [ +
+ +
, + ], + /*: []*/ + ]} + selected={orderedTabs.indexOf(tab)} + onClick={idx => setTab(orderedTabs[idx] as any)} + /> + + + {tab === 'all' && } + {tab === 'messages' && } + {tab === 'medias' && } + {tab === 'files' && } + {tab === 'channels' && } + + + ); +}; + +const ChannelsTab = () => { + const input = useRecoilValue(SearchInputState); + const hasInput = input?.query?.length > 0; + const { channels } = useSearchChannels(); + + return ( +
+ {Languages.t('components.searchpopup.channels')} + {hasInput && } +
+ ); +}; + +const SearchCounterBadge = (props: { count: number }) => { + const count = props.count < 100 ? props.count : '99+'; + return ( +
+ {count} +
+ ); +}; diff --git a/twake/frontend/src/app/components/search-popup/tabs/all.tsx b/twake/frontend/src/app/components/search-popup/tabs/all.tsx new file mode 100644 index 0000000000..89597474b2 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/tabs/all.tsx @@ -0,0 +1,117 @@ +import * as Text from '@atoms/text'; +import A from 'app/atoms/link'; +import Languages from 'app/features/global/services/languages-service'; +import { useSearchChannels } from 'app/features/search/hooks/use-search-channels'; +import { + useSearchMessagesFiles, + useSearchMessagesMedias, +} from 'app/features/search/hooks/use-search-files-or-medias'; +import { useSearchMessages } from 'app/features/search/hooks/use-search-messages'; +import { SearchInputState, SearchTabsState } from 'app/features/search/state/search-input'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { ChannelsResults, ChannelsRowResults } from './channels'; +import { FilesResults } from './files'; +import { MediasResults } from './medias'; +import { MessagesResults } from './messages'; + +export default () => { + const setTab = useSetRecoilState(SearchTabsState); + + const input = useRecoilValue(SearchInputState); + const isRecent = input?.query?.trim()?.length === 0; + + const { channels } = useSearchChannels(); + const { messages } = useSearchMessages(); + const { files } = useSearchMessagesFiles(); + const { files: medias } = useSearchMessagesMedias(); + + return ( +
+ {channels.length > 0 && ( + <> +
+ + {isRecent + ? Languages.t('components.searchpopup.recent_channels_and_contacts') + : Languages.t('components.searchpopup.channels')} + + {channels.length > 6 && ( + + )} +
+ {isRecent && ( +
+ +
+ )} + {!isRecent && ( +
+ +
+ )} + + )} + + {medias.length > 0 && ( + <> +
+ + {isRecent + ? Languages.t('components.searchpopup.recent_media') + : Languages.t('components.searchpopup.media')} + + {medias.length > 6 && ( + + )} +
+
+ +
+ + )} + + {files.length > 0 && ( + <> +
+ + {isRecent + ? Languages.t('components.searchpopup.recent_files') + : Languages.t('components.searchpopup.files')} + + {files.length > 6 && ( + + )} +
+
+ +
+ + )} + + {messages.length > 0 && ( + <> +
+ + {Languages.t('components.searchpopup.messages')} + +
+
+ +
+ + )} +
+ ); +}; diff --git a/twake/frontend/src/app/components/search-popup/tabs/channels.tsx b/twake/frontend/src/app/components/search-popup/tabs/channels.tsx new file mode 100644 index 0000000000..cb3d9052f8 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/tabs/channels.tsx @@ -0,0 +1,87 @@ +import * as Text from '@atoms/text'; +import Languages from 'app/features/global/services/languages-service'; +import { useSearchChannels } from 'app/features/search/hooks/use-search-channels'; +import { SearchInputState } from 'app/features/search/state/search-input'; +import { useRecoilValue } from 'recoil'; +import ChannelLineResult from '../parts/channel-line-result'; +import ChannelResult from '../parts/channel-result'; +import NothingFound from '../parts/nothing-found'; + +export default () => { + const input = useRecoilValue(SearchInputState); + const isRecent = input?.query?.trim()?.length === 0; + const { channels, loading } = useSearchChannels(); + + if (channels.length === 0 && !loading) return ; + + const topChannels = channels + .slice() + .filter(a => Date.now() - (a.last_activity || 0) < 1000 * 60 * 60 * 24 * 31) + .sort((a, b) => Math.min(50, b?.stats?.messages || 0) - Math.min(50, a?.stats?.messages || 0)) + .slice(0, 5); + + return ( +
+ {!!isRecent && !!topChannels.length && ( +
+ + {Languages.t('components.searchpopup.recent_channels_and_contacts')} + + +
+ {topChannels.map(channel => ( +
+ +
+ ))} +
+
+ )} + + {!!isRecent && ( + + {Languages.t('components.searchpopup.channels')} + + )} +
+ +
+
+ ); +}; + +export const ChannelsRowResults = (props: { max?: number }) => { + const { channels, loading } = useSearchChannels(); + + if (channels.length === 0 && !loading) return ; + + return ( + <> + {channels.slice(0, props?.max || channels.length).map(channel => ( +
+ +
+ ))} + + ); +}; + +export const ChannelsResults = (props: { max?: number }) => { + const { channels, loading } = useSearchChannels(); + + if (channels.length === 0 && !loading) return ; + + return ( + <> + {channels.slice(0, props?.max || channels.length).map(channel => ( + + ))} + + ); +}; diff --git a/twake/frontend/src/app/components/search-popup/tabs/files.tsx b/twake/frontend/src/app/components/search-popup/tabs/files.tsx new file mode 100644 index 0000000000..6a6d18cc04 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/tabs/files.tsx @@ -0,0 +1,43 @@ +import * as Text from '@atoms/text'; +import Languages from 'app/features/global/services/languages-service'; +import { useSearchMessagesFiles } from 'app/features/search/hooks/use-search-files-or-medias'; +import { SearchInputState } from 'app/features/search/state/search-input'; +import { useRecoilValue } from 'recoil'; +import FileResult from '../parts/file-result'; +import NothingFound from '../parts/nothing-found'; + +export default () => { + const input = useRecoilValue(SearchInputState); + const isRecent = input?.query?.trim()?.length === 0; + const { files, loading } = useSearchMessagesFiles(); + + if (files.length === 0 && !loading) return ; + + return ( +
+ {!!isRecent && ( + + {Languages.t('components.searchpopup.recent_files')} + + )} + +
+ +
+
+ ); +}; + +export const FilesResults = (props: { max?: number }) => { + const { files, loading } = useSearchMessagesFiles(); + + if (files.length === 0 && !loading) return ; + + return ( + <> + {files.slice(0, props?.max || files.length).map(file => ( + + ))} + + ); +}; diff --git a/twake/frontend/src/app/components/search-popup/tabs/medias.tsx b/twake/frontend/src/app/components/search-popup/tabs/medias.tsx new file mode 100644 index 0000000000..76ce0373ef --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/tabs/medias.tsx @@ -0,0 +1,51 @@ +import * as Text from '@atoms/text'; +import FileUploadAPIClient from '@features/files/api/file-upload-api-client'; +import Languages from '@features/global/services/languages-service'; +import { useSearchMessagesMedias } from '@features/search/hooks/use-search-files-or-medias'; +import { SearchInputState } from '@features/search/state/search-input'; +import { useRecoilValue } from 'recoil'; +import FileResult from '../parts/file-result'; +import MediaResult from '../parts/media-result'; +import NothingFound from '../parts/nothing-found'; + +export default () => { + const input = useRecoilValue(SearchInputState); + const isRecent = input?.query?.trim()?.length === 0; + + return ( +
+ {!!isRecent && ( + + {Languages.t('components.searchpopup.recent_media')} + + )} + +
+ +
+
+ ); +}; + +export const MediasResults = (props: { max?: number; showAsFiles?: boolean }) => { + const { files, loading } = useSearchMessagesMedias(); + + if (files.length === 0 && !loading) return ; + + return ( + <> + {files + .slice(0, props?.max || files.length) + .map(file => { + const url = FileUploadAPIClient.getFileThumbnailUrlFromMessageFile(file); + if (url || props.showAsFiles) + return props.showAsFiles ? ( + + ) : ( + + ); + }) + .filter(a => a)} + + ); +}; diff --git a/twake/frontend/src/app/components/search-popup/tabs/messages.tsx b/twake/frontend/src/app/components/search-popup/tabs/messages.tsx new file mode 100644 index 0000000000..c840d4f819 --- /dev/null +++ b/twake/frontend/src/app/components/search-popup/tabs/messages.tsx @@ -0,0 +1,43 @@ +import * as Text from '@atoms/text'; +import Languages from '@features/global/services/languages-service'; +import { SearchInputState } from '@features/search/state/search-input'; +import { useSearchMessages } from 'app/features/search/hooks/use-search-messages'; +import { useRecoilValue } from 'recoil'; +import MessageResult from '../parts/message-result'; +import NothingFound from '../parts/nothing-found'; +import NothingSearched from '../parts/nothing-searched'; + +export default () => { + return ( +
+
+ +
+
+ ); +}; + +export const MessagesResults = (props: { max?: number }) => { + const input = useRecoilValue(SearchInputState); + const isRecent = input?.query?.trim()?.length === 0; + const { messages, loading, loadMore } = useSearchMessages(); + + if (isRecent) return ; + if (messages.length === 0 && !loading) return ; + + return ( + <> +
+ {messages + .map(message => { + return ( +
+ +
+ ); + }) + .filter(a => a)} +
+ + ); +}; diff --git a/twake/frontend/src/app/components/select/select.js b/twake/frontend/src/app/components/select/select.js new file mode 100755 index 0000000000..9304e70711 --- /dev/null +++ b/twake/frontend/src/app/components/select/select.js @@ -0,0 +1,71 @@ +import React, { Component } from 'react'; + +import MenusManager from 'app/components/menus/menus-manager.js'; +import Icon from 'components/icon/icon.js'; +import './select.scss'; + +export default class Select extends React.Component { + constructor(props) { + super(); + this.props = props; + } + select(value) { + this.props.onChange(value); + } + openMenu(evt) { + var pos = window.getBoundingClientRect(this.node); + pos.x = pos.x || pos.left; + pos.y = pos.y || pos.top; + MenusManager.openMenu( + this.props.options.map(item => { + return { + type: item.type || 'menu', + text: item.text, + className: item.className, + icon: item.icon, + emoji: item.emoji, + reactElement: item.reactElement, + onClick: () => this.select(item.value), + }; + }), + { x: pos.x + pos.width / 2, y: pos.y + pos.height }, + 'bottom', + ); + } + render() { + var className = this.props.className || ''; + + if (this.props.big) { + className += ' big '; + } + if (this.props.medium) { + className += ' medium '; + } + if (this.props.small) { + className += ' small '; + } + + if ( + className.indexOf('medium') === className.indexOf('small') && + className.indexOf('big') === className.indexOf('small') && + className.indexOf('big') < 0 + ) { + className += ' small'; + } + + var current = + this.props.options.filter(item => { + return item.value == this.props.value; + })[0] || {}; + + return ( +
(this.node = node)} + className={'select ' + className} + onClick={evt => this.openMenu(evt)} + > + {current.icon && } {current.text || current.title || '-'} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/Select/Select.scss b/twake/frontend/src/app/components/select/select.scss similarity index 100% rename from twake/frontend/src/app/components/Select/Select.scss rename to twake/frontend/src/app/components/select/select.scss diff --git a/twake/frontend/src/app/components/step-counter/step-counter.js b/twake/frontend/src/app/components/step-counter/step-counter.js new file mode 100755 index 0000000000..b78e96f6e2 --- /dev/null +++ b/twake/frontend/src/app/components/step-counter/step-counter.js @@ -0,0 +1,37 @@ +import React, { Component } from 'react'; + +import './step-counter.scss'; + +export default class StepCounter extends React.Component { + /* + props : { + current : int + total : int + } + */ + constructor() { + super(); + } + displayStep() { + var ret = []; + for (var i = 0; i < this.props.total; i++) { + ret.push( +
, + ); + } + return ret; + } + render() { + return ( +
+ {this.displayStep().map(item => { + return item; + })} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/StepCounter/StepCounter.scss b/twake/frontend/src/app/components/step-counter/step-counter.scss similarity index 100% rename from twake/frontend/src/app/components/StepCounter/StepCounter.scss rename to twake/frontend/src/app/components/step-counter/step-counter.scss diff --git a/twake/frontend/src/app/components/table/table.scss b/twake/frontend/src/app/components/table/table.scss new file mode 100755 index 0000000000..7feb9aaf38 --- /dev/null +++ b/twake/frontend/src/app/components/table/table.scss @@ -0,0 +1,98 @@ +rm .table { + overflow: hidden; + border-radius: var(--border-radius-base); + margin-bottom: 16px; + border: 1px solid var(--grey-background); + font-weight: 500; + + &.unfocused { + box-shadow: none; + } + + &.loading { + opacity: 0.5; + + .tr .item .line { + pointer-events: none; + border-radius: var(--border-radius-large); + height: 16px; + margin-top: 8px; + width: 200px; + animation-duration: 1s; + animation-fill-mode: forwards; + animation-iteration-count: infinite; + animation-name: placeHolderShimmer; + animation-timing-function: linear; + background-repeat: repeat !important; + background-image: linear-gradient( + to right, + var(--grey-light) 0px, + #f2f2f2 120px, + var(--grey-light) 234px + ) !important; + + & > * { + opacity: 0 !important; + } + } + } + + .headerTable { + background: var(--grey-background); + font-weight: 700; + font-size: 14px; + display: flex; + padding: 8px; + border-bottom: 1px solid var(--grey-background); + } + + .footerTable { + text-align: center; + line-height: 32px; + font-size: 14px; + padding: 5px 10px; + border-top: 1px solid var(--grey-background); + border-bottom: 1px solid var(--grey-background); + } + .contentTable { + .tr { + display: flex; + border-bottom: 1px solid var(--grey-background); + padding: 8px; + font-size: 12px; + + &:hover { + background: var(--grey-background); + } + + &:last-child { + border-bottom: none; + } + + & > div { + position: relative; + min-height: 32px; + + & > .absolute_position { + width: 100%; + position: absolute; + height: 100%; + display: flex; + } + } + } + + .fix_text_padding_medium { + padding: 8px 0; + display: inline-block; + line-height: 18px; + } + + .text-complete-width { + overflow: hidden; + flex: 1; + white-space: nowrap; + text-overflow: ellipsis; + } + } +} diff --git a/twake/frontend/src/app/components/table/table.tsx b/twake/frontend/src/app/components/table/table.tsx new file mode 100755 index 0000000000..fe8ea07384 --- /dev/null +++ b/twake/frontend/src/app/components/table/table.tsx @@ -0,0 +1,244 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import React, { Component } from 'react'; +import Languages from 'app/features/global/services/languages-service'; +import Button from 'components/buttons/button.js'; +import InputIcon from 'components/inputs/input-icon.js'; +import './table.scss'; + +type Props = { + column?: any; + noHeader: boolean; + onAdd: () => void; + onRequestMore: (refresh: boolean) => Promise; + onSearch: (query: string, maxResults: number, callback: (res: any[]) => void) => Promise; + updatedData: (data: any) => any; + addText?: string; + resultsPerPage?: number; + unFocused: boolean; +}; +type State = { + data: null | any[]; + searchResults: any[]; + loading: boolean; + has_more: boolean; + page: number; + searching: boolean; +}; + +export default class Table extends Component { + searchFieldValue = ''; + searchRunning = false; + searchRunningTimeout: number | null = null; + + constructor(props: Props) { + super(props); + this.state = { + data: null, + searchResults: [], + loading: true, + has_more: true, + page: 0, + searching: false, + }; + Languages.addListener(this); + } + + componentWillUnmount() { + Languages.removeListener(this); + } + + componentDidMount() { + if (this.state.data === null) { + this.requestMore(true); + } + } + + search() { + if (this.searchFieldValue?.length <= 2) { + return false; + } + if (this.searchRunning) { + //@ts-ignore + clearTimeout(this.searchRunningTimeout); + //@ts-ignore + this.searchRunningTimeout = setTimeout(() => { + this.search(); + }, 1000); + return; + } + + this.setState({ + loading: true, + }); + + this.searchRunning = true; + this.props.onSearch(this.searchFieldValue, 10, (data: any[]) => { + this.searchRunning = false; + this.setState({ + loading: false, + searchResults: data, + }); + }); + } + + renderItem(col: any, item: any) { + if (col.render) { + return col.render(item); + } else { + return
{col.dataIndex ? item[col.dataIndex] : ''}
; + } + } + + requestMore(refresh = false) { + this.setState({ loading: true }); + this.props.onRequestMore(refresh).then(res => { + const hasMore = res.length !== (this.state.data || []).length; + this.setState({ loading: false, data: res, has_more: hasMore }); + }); + } + + setPosition() { + if (this.props.onSearch && !this.props.onAdd) return 'flex-end'; + else return 'space-between'; + } + + nextPage() { + this.setState({ page: this.state.page + 1 }); + if (this.getPageData().length < (this.state.page + 1) * this.getResultsPerPage()) { + this.requestMore(); + } + } + + getPageData() { + const from = this.state.page * this.getResultsPerPage(); + return (this.state.data || []).slice(0, from + this.getResultsPerPage()); + } + + getResultsPerPage(): number { + return this.props.resultsPerPage || 50; + } + + render() { + let page_data = this.state.searching ? this.state.searchResults : this.getPageData(); + page_data = page_data + .map(data => { + data = this.props.updatedData ? this.props.updatedData(data) : data; + if (!data) { + return false; + } + return data; + }) + .filter(i => i); + + return ( +
+
+ {this.props.onAdd && ( +
+ +
+ {!this.props.noHeader && ( +
+ {this.props.column.map((col: any, i: number) => { + return ( +
+ {col.title} +
+ ); + })} +
+ )} +
+ {(page_data || []).length === 0 && !this.state.loading && ( +
+
+ {Languages.t('components.user_picker.modal_no_result')} +
+
+ )} + {(page_data || []).length === 0 && + !!this.state.loading && + Array(this.state.searching ? 1 : this.getResultsPerPage()).map((_, i: number) => { + return ( +
+
+
+
+
+ ); + })} + {(page_data || []).map((data: any, i: number) => { + return ( +
+ {this.props.column.map((col: any, j: number) => { + return ( +
+ {this.renderItem(col, data)} +
+ ); + })} +
+ ); + })} +
+ {!this.state.searching && + !!this.state.has_more && + page_data.length >= this.getResultsPerPage() && ( + + )} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/tabs/tabs.js b/twake/frontend/src/app/components/tabs/tabs.js new file mode 100755 index 0000000000..a369f2b76f --- /dev/null +++ b/twake/frontend/src/app/components/tabs/tabs.js @@ -0,0 +1,68 @@ +import React, { Component } from 'react'; + +import Languages from 'app/features/global/services/languages-service'; +import PerfectScrollbar from 'react-perfect-scrollbar'; +import './tabs.scss'; + +export default class Tabs extends Component { + constructor(props) { + super(props); + this.state = { + i18n: Languages, + tab: props.selected, + }; + Languages.addListener(this); + } + componentWillUnmount() { + Languages.removeListener(this); + } + select(i) { + this.setState({ tab: i }); + this.props.onChange && this.props.onChange(i); + } + componentWillUpdate(nextProps, nextState) { + if (nextProps.selected && JSON.stringify(nextProps.selected) != this.oldSelected) { + nextState.tab = nextProps.selected; + this.oldSelected = JSON.stringify(nextProps.selected); + } + } + render() { + var selected = this.state.tab || Object.keys(this.props.tabs || {})[0]; + if (!this.props.tabs[selected]) { + selected = Object.keys(this.props.tabs || {})[0]; + } + + return ( +
+ + {Object.keys(this.props.tabs || {}).map(i => { + var item = this.props.tabs[i]; + return ( +
this.select(i)} + > + {typeof item.title == 'function' ? item.title() : item.title} +
+ ); + })} +
+
+ {typeof this.props.tabs[selected].render == 'function' + ? this.props.tabs[selected].render() + : this.props.tabs[selected].render} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/Tabs/Tabs.scss b/twake/frontend/src/app/components/tabs/tabs.scss similarity index 100% rename from twake/frontend/src/app/components/Tabs/Tabs.scss rename to twake/frontend/src/app/components/tabs/tabs.scss diff --git a/twake/frontend/src/app/components/tag-picker/tag-picker.js b/twake/frontend/src/app/components/tag-picker/tag-picker.js new file mode 100755 index 0000000000..72ffcd93bf --- /dev/null +++ b/twake/frontend/src/app/components/tag-picker/tag-picker.js @@ -0,0 +1,194 @@ +import React, { Component } from 'react'; +import Icon from 'components/icon/icon.js'; +import Button from 'components/buttons/button.js'; +import './tag-picker.scss'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import TagSelector from './tag-selector.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Languages from 'app/features/global/services/languages-service'; + +export default class TagPicker extends React.Component { + constructor(props) { + super(); + this.props = props; + this.state = { + currentSelected: [], + inputValue: '', + currentList: [], + selected: [], + value: this.props.value || [], + list: props.data || [ + { id: 1, name: Languages.t('scenes.apps.tasks.task_status.todo', [], 'To do') }, + { id: 2, name: Languages.t('scenes.apps.tasks.task_status.current', [], 'Doing') }, + { id: 3, name: Languages.t('scenes.apps.tasks.task_status.done', [], 'Done') }, + ], + }; + } + componentWillUpdate(nextProps, nextState) { + if (JSON.stringify(nextProps.value) != JSON.stringify(this.props.value)) { + this.state.value = nextProps.value; + } + } + componentWillMount() { + if (!this.props.data) { + Collections.get('tags').addListener(this); + Collections.get('tags').addSource( + { + http_base_url: 'globalsearch/tags', + http_options: { + workspace_id: Workspaces.currentWorkspaceId, + }, + websockets: [{ uri: 'tags/' + Workspaces.currentWorkspaceId, options: { type: 'tags' } }], + }, + Workspaces.currentWorkspaceId, + ); + } + } + componentWillUnmount() { + if (!this.props.data) { + Collections.get('tags').removeListener(this); + } + } + addTags(evt) { + var menu = [ + { + type: 'react-element', + reactElement: level => { + return ( + { + if (typeof a == 'string') { + return { name: a, id: a, color: '#888' }; + } else { + return a; + } + }) + : false + } + canCreate={this.props.canCreate} + disabledTags={ + this.state.value.map(item => { + return typeof item == 'string' ? item : item.id; + }) || [] + } + onChange={value => { + value.forEach(tag => { + if ( + this.state.value + .map(item => { + return typeof item == 'string' ? item : item.id; + }) + .indexOf(tag.id || tag.name || tag) < 0 + ) { + this.state.value.push(tag.id || tag.name || tag); + } + }); + if (!this.props.saveButton) this.props.onChange(this.state.value); + this.setState({}); + if (this.props.menu_level !== undefined) { + MenusManager.closeSubMenu(this.props.menu_level); + } else { + MenusManager.closeMenu(); + } + }} + /> + ); + }, + }, + ]; + if (this.props.menu_level !== undefined) { + MenusManager.openSubMenu( + menu, + { x: evt.clientX, y: evt.clientY }, + this.props.menu_level, + 'right', + ); + } else { + MenusManager.openMenu(menu, { x: evt.clientX, y: evt.clientY }, 'right'); + } + } + render() { + var value = this.state.value || []; + + var tag_list = value.map(tag_id => { + var tag = false; + if (this.props.data) { + if (typeof tag_id == 'string') { + tag = { name: tag_id, id: tag_id, color: '#888' }; + } else { + tag = tag_id; + tag.id = tag.id || tag.name; + tag.color = tag.color || '#888'; + } + } else { + tag = Collections.get('tags').find(tag_id); + } + if (!tag) { + return ''; + } + var name = tag.name; + return ( +
+ {name}{' '} + {!this.props.readOnly && ( + { + this.state.value.splice(this.state.value.indexOf(tag.id), 1); + if (!this.props.saveButton) this.props.onChange(this.state.value); + this.setState({}); + }} + /> + )} +
+ ); + }); + + if (this.props.inline) { + return tag_list; + } + + return ( +
+ {!this.props.readOnly && value.length == 0 && ( +
{Languages.t('components.tagpicker.notag', [], 'No tag')}
+ )} + + {tag_list} + + {!this.props.readOnly && ( + + )} + + {this.props.saveButton && ( +
+
+ )} +
+ ); + } +} diff --git a/twake/frontend/src/app/components/TagPicker/TagPicker.scss b/twake/frontend/src/app/components/tag-picker/tag-picker.scss similarity index 100% rename from twake/frontend/src/app/components/TagPicker/TagPicker.scss rename to twake/frontend/src/app/components/tag-picker/tag-picker.scss diff --git a/twake/frontend/src/app/components/tag-picker/tag-selector.js b/twake/frontend/src/app/components/tag-picker/tag-selector.js new file mode 100755 index 0000000000..05336ec6cc --- /dev/null +++ b/twake/frontend/src/app/components/tag-picker/tag-selector.js @@ -0,0 +1,219 @@ +import React, { Component } from 'react'; +import Picker from 'components/picker/picker.js'; +import Button from 'components/buttons/button.js'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Icon from 'components/icon/icon.js'; +import ColorPicker from 'components/color-picker/color-picker.js'; +import Strings from 'app/features/global/utils/strings'; +import InputWithColor from 'components/inputs/input-with-color.js'; +import AlertManager from 'app/features/global/services/alert-manager-service'; +import Languages from 'app/features/global/services/languages-service'; +import MenusManager from 'app/components/menus/menus-manager.js'; + +class TagEditor extends React.Component { + constructor(props) { + super(); + this.props = props; + this.state = { + edited_tag_name: '', + edited_tag_color: '', + }; + } + componentWillMount() { + var tag = this.props.tag; + this.state.edited_tag_color = tag.color; + this.state.edited_tag_name = tag.name; + } + saveTag(tag) { + tag.color = this.state.edited_tag_color || tag.color; + tag.name = this.state.edited_tag_name || tag.name; + Collections.get('tags').save(tag, Workspaces.currentWorkspaceId); + MenusManager.closeSubMenu(this.props.level - 1); + } + render() { + var tag = this.props.tag; + return ( +
+ { + this.saveTag(tag); + }} + onChange={value => { + this.setState({ edited_tag_color: value[0], edited_tag_name: value[1] }); + }} + /> +
+
+
+ ); + } +} + +export default class TagSelector extends React.Component { + constructor(props) { + super(); + this.props = props; + this.state = { + edited_tag_name: '', + edited_tag_color: '', + }; + + this.colors_random_list = ColorPicker.colors.map(a => a).sort(() => Math.random() - 0.5); + this.next_new_color = 0; + } + onUpdate(item) {} + onCreate(text, cb) { + var color = this.colors_random_list[this.next_new_color]; + this.next_new_color = (this.next_new_color + 1) % this.colors_random_list.length; + + var new_tag = Collections.get('tags').edit(); + new_tag.name = text; + new_tag.color = color; + new_tag.workspace_id = Workspaces.currentWorkspaceId; + Collections.get('tags').save(new_tag, Workspaces.currentWorkspaceId, tag => { + cb(new_tag); + }); + + return new_tag; + } + onRemove(item, ev) {} + renderItemChoosen(item) { + return ''; + } + editTag(evt, id) { + var tag = Collections.get('tags').find(id); + if (!tag) { + return; + } + var menu = [ + { type: 'title', text: Languages.t('general.edit') }, + { + type: 'react-element', + reactElement: level => { + return ; + }, + }, + { type: 'separator' }, + { + text: Languages.t('general.remove'), + className: 'error', + icon: 'trash', + onClick: ev => { + var tag = Collections.get('tags').find(id); + if (tag) { + AlertManager.confirm(() => { + MenusManager.closeSubMenu(this.props.level - 1); + Collections.get('tags').remove(tag, Workspaces.currentWorkspaceId); + }); + } + return false; + }, + }, + ]; + MenusManager.openSubMenu(menu, { x: evt.clientX, y: evt.clientY }, this.props.level, 'right'); + } + renderItem(item) { + var add_option = false; + if (typeof item == 'string') { + add_option = true; + item = { name: item, color: this.colors_random_list[this.next_new_color] }; + } + var tag = ( +
= 0 ? 'disabled' : '') + } + style={{ backgroundColor: item.color, margin: '5px 0' }} + > + {item.name} +
+ ); + + if (add_option) { + return tag; + } + + return ( +
+
{tag}
+ {!add_option && !this.props.data && ( +
{ + ev.stopPropagation(); + ev.preventDefault(); + this.editTag(ev, item.id); + }} + > + +
+ )} +
+ ); + } + search(text, cb) { + var res = Collections.get('tags').findBy({ workspace_id: Workspaces.currentWorkspaceId }); + if (this.props.data) { + res = this.props.data; + } + + res = res + .filter(function (item) { + if ( + Strings.removeAccents(item.name.toLowerCase().replace(/ +/, '')).indexOf( + Strings.removeAccents(text.toLowerCase().replace(/ +/, '')), + ) !== -1 + ) { + return true; + } + return false; + }) + .sort((a, b) => { + return this.props.disabledTags.indexOf(a.id) >= 0 ? -1 : 1; + }); + cb(res); + } + render() { + return ( + { + this.picker = picker; + }} + title={false} + search={(text, cb) => { + this.search(text, cb); + }} + renderItem={item => { + return this.renderItem(item); + }} + renderItemChoosen={item => { + return this.renderItemChoosen(item); + }} + renderItemSimply={item => { + return item.name; + }} + canCreate={this.props.canCreate !== false} + onCreate={(text, cb) => this.onCreate(text, cb)} + onSelect={item => this.onSelect(item)} + onChange={this.props.onChange} + value={this.props.value} + readOnly={this.props.readOnly} + inline={this.props.inline} + /> + ); + } +} diff --git a/twake/frontend/src/app/components/task-picker/task-picker.js b/twake/frontend/src/app/components/task-picker/task-picker.js new file mode 100755 index 0000000000..d711e462bd --- /dev/null +++ b/twake/frontend/src/app/components/task-picker/task-picker.js @@ -0,0 +1,254 @@ +import React, { Component } from 'react'; +import Workspaces from 'app/deprecated/workspaces/workspaces.js'; +import Button from 'components/buttons/button.js'; +import Languages from 'app/features/global/services/languages-service'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections.js'; +import Emojione from 'components/emojione/emojione'; +import Loader from 'components/loader/loader.js'; +import TasksService from 'app/deprecated/Apps/Tasks/Tasks.js'; +import LeftIcon from '@material-ui/icons/KeyboardArrowLeftOutlined'; + +import './task-picker.scss'; + +export default class TaskPicker extends Component { + /* + props : { + mode : "select_board" / "select_task" + } + */ + + constructor(props) { + super(props); + this.tasks_collection_key = 'tasks_picker_' + Workspaces.currentWorkspaceId; + this.collection_key = []; + + this.state = { + taskRepository: Collections.get('task'), + currentBoard: null, + currentList: null, + taskSelected: null, + boardRepository: Collections.get('boards'), + }; + Languages.addListener(this); + Collections.get('boards').addListener(this); + Collections.get('lists').addListener(this); + Collections.get('tasks').addListener(this); + Collections.get('boards').addSource( + { + http_base_url: 'tasks/board', + http_options: { + workspace_id: Workspaces.currentWorkspaceId, + }, + websockets: [ + { uri: 'boards/' + Workspaces.currentWorkspaceId, options: { type: 'board' } }, + ], + }, + this.tasks_collection_key, + ); + } + componentWillUnmount() { + Languages.removeListener(this); + Collections.get('boards').removeSource(this.tasks_collection_key); + Collections.get('lists').removeSource(this.tasks_collection_key); + Collections.get('tasks').removeSource(this.tasks_collection_key); + Collections.get('boards').removeListener(); + Collections.get('lists').removeListener(); + Collections.get('tasks').removeListener(); + } + selectBoard(board) { + if (this.collection_key.indexOf(this.tasks_collection_key + '_' + board.id) < 0) { + this.collection_key.push(this.tasks_collection_key + '_' + board.id); + Collections.get('lists').addSource( + { + http_base_url: 'tasks/list', + http_options: { + board_id: board.id, + }, + websockets: [{ uri: 'board_lists/' + board.id, options: { type: 'list' } }], + }, + this.tasks_collection_key + '_' + board.id, + ); + Collections.get('tasks').addSource( + { + http_base_url: 'tasks/task', + http_options: { + board_id: board.id, + }, + websockets: [{ uri: 'board_tasks/' + board.id, options: { type: 'task' } }], + }, + this.tasks_collection_key + '_' + board.id + '_tasks', + ); + } + this.setState({ currentBoard: board }); + } + selectList(list) { + this.setState({ currentList: list }); + } + selectTask(task) { + this.setState({ taskSelected: task }); + } + submit() { + if (this.props.mode === 'select_task' && this.state.taskSelected) { + if (this.props.onChoose) { + this.props.onChoose(this.state.taskSelected); + } + } + } + renderBoardPicker() { + var boards = Collections.get('boards').findBy({ workspace_id: Workspaces.currentWorkspaceId }); + var loading = + !Collections.get('boards').did_load_first_time[this.tasks_collection_key] && + boards.length === 0; + return ( +
+ {loading && ( +
+ +
+ )} + {!loading && + boards.map(board => { + return ( +
this.selectBoard(board)}> +
+ {board.emoji && ( + + )} +
{board.title}
+
+
+ ); + })} +
+ ); + } + renderListPicker() { + var loading = + !Collections.get('lists').did_load_first_time[ + this.tasks_collection_key + '_' + this.state.currentBoard.id + ]; + var lists = Collections.get('lists').findBy({ board_id: this.state.currentBoard.id }); + return ( +
+ {loading && ( +
+ +
+ )} + {!loading && + lists + .sort( + (a, b) => + TasksService.getElementIndex(a, 'lists_' + a.board_id) - + TasksService.getElementIndex(b, 'lists_' + b.board_id), + ) + .map((item, index) => { + return ( +
{ + this.selectList(item); + }} + > +
+
{item.title}
+
+ ); + })} +
+ ); + } + renderTaskPicker() { + var loading = + !Collections.get('tasks').did_load_first_time[ + this.tasks_collection_key + '_' + this.state.currentBoard.id + '_tasks' + ]; + var tasks = Collections.get('tasks').findBy({ + board_id: this.state.currentBoard.id, + list_id: this.state.currentList.id, + archived: false, + }); + return ( +
+ {loading && ( +
+ +
+ )} + {!loading && + (tasks || []) + .sort( + (a, b) => + TasksService.getElementIndex(a, 'tasks_' + a.list_id) - + TasksService.getElementIndex(b, 'tasks_' + b.list_id), + ) + .map((item, index) => ( +
{ + this.selectTask(item); + }} + > +
{item.title}
+
+ ))} +
+ ); + } + render() { + return ( +
+ {!this.state.currentBoard && ( +
{Languages.t('scenes.apps.tasks.task')}
+ )} + {this.state.currentBoard && !this.state.currentList && ( +
+ { + Collections.get('lists').removeListener(); + this.setState({ currentBoard: null }); + }} + /> + {this.state.currentBoard.title} +
+ )} + {this.state.currentBoard && this.state.currentList && ( +
+ { + Collections.get('tasks').removeListener(); + this.setState({ currentList: null }); + }} + /> + {this.state.currentBoard.title} - {this.state.currentList.title} +
+ )} +
+ {!this.state.currentBoard && this.renderBoardPicker()} + {this.state.currentBoard && !this.state.currentList && this.renderListPicker()} + {this.state.currentBoard && this.state.currentList && this.renderTaskPicker()} +
+
+ {this.props.mode === 'select_task' && + this.state.taskSelected && + this.state.taskSelected.id && ( +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/TaskPicker/TaskPicker.scss b/twake/frontend/src/app/components/task-picker/task-picker.scss similarity index 100% rename from twake/frontend/src/app/components/TaskPicker/TaskPicker.scss rename to twake/frontend/src/app/components/task-picker/task-picker.scss diff --git a/twake/frontend/src/app/components/tooltip/tooltip.js b/twake/frontend/src/app/components/tooltip/tooltip.js new file mode 100755 index 0000000000..dd31d61fe4 --- /dev/null +++ b/twake/frontend/src/app/components/tooltip/tooltip.js @@ -0,0 +1,113 @@ +import React, { Component } from 'react'; + +import './tooltip.scss'; + +export default class Tooltip extends Component { + /* + props = { + tooltip : text or react element to show + visible : + overable : default : true + position : + } + */ + constructor(props) { + super(props); + this.state = { + top: 'unset', + left: 'unset', + right: 'unset', + bottom: '0px', + }; + } + componentWillUnmount() {} + componentDidUpdate(prevProps, prevState) { + if (this.props.visible === true && prevProps.visible === false) { + this.open(); + } else if (this.props.visible === false && prevProps.visible === true) { + this.close(); + } + } + openWithTimeOut(timeout = 5) { + var that = this; + that.open(); + setTimeout(() => { + that.close(); + }, timeout * 1000); + } + open() { + if (this.props.position === 'left') { + this.setState({ + visible: true, + left: (this.tooltip.clientWidth + 8) * -1 + 'px', + right: 'unset', + }); + } else if (this.props.position === 'right') { + this.setState({ + visible: true, + right: (this.tooltip.clientWidth + 8) * -1 + 'px', + left: 'unset', + }); + } else if (this.props.position === 'bottom') { + this.setState({ + visible: true, + bottom: (this.tooltip.clientHeight + 5) * -1 + 'px', + top: 'unset', + }); + } else { + this.setState({ + visible: true, + top: (this.tooltip.clientHeight + 5) * -1 + 'px', + bottom: 'unset', + }); + } + } + close() { + this.setState({ visible: false, top: 'unset', left: '0px', right: 'unset', bottom: '0px' }); + } + componentDidMount() { + var that = this; + if (this.parent && this.children) { + window.tooltip = this.tooltip; + this.parent.addEventListener('mouseenter', () => { + if (this.props.overable !== false) { + that.open(); + } + }); + this.parent.addEventListener('mouseleave', () => { + if (this.props.overable !== false) { + that.close(); + } + }); + } + } + render() { + return ( +
(this.parent = parent)} + > +
(this.tooltip = obj)} + > + {this.props.tooltip} +
+
(this.children = children)}> + {this.props.children} +
+
+ ); + } +} diff --git a/twake/frontend/src/app/components/Tooltip/Tooltip.scss b/twake/frontend/src/app/components/tooltip/tooltip.scss similarity index 100% rename from twake/frontend/src/app/components/Tooltip/Tooltip.scss rename to twake/frontend/src/app/components/tooltip/tooltip.scss diff --git a/twake/frontend/src/app/components/twacode/blocks/chan.tsx b/twake/frontend/src/app/components/twacode/blocks/chan.tsx new file mode 100755 index 0000000000..c05db28335 --- /dev/null +++ b/twake/frontend/src/app/components/twacode/blocks/chan.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import Emojione from 'components/emojione/emojione'; +import MainViewService from 'app/features/router/services/main-view-service'; +import { useChannel } from 'app/features/channels/hooks/use-channel'; + +type PropsType = { + // channel id + id: string; + // channel name + name: string; +}; + +export default (props: PropsType): JSX.Element => { + const { channel } = useChannel(props.id); + + if (!props.id || !channel) { + return #{props.name}; + } + + return ( +
{ + MainViewService.select(props.id, { + app: { + identity: { + code: 'messages', + name: '', + icon: '', + description: '', + website: '', + categories: [], + compatibility: [], + }, + }, + context: { type: 'channel' }, + hasTabs: channel.visibility !== 'direct', + }); + }} + > + + {channel.name} +
+ ); +}; diff --git a/twake/frontend/src/app/components/twacode/blocks/user.tsx b/twake/frontend/src/app/components/twacode/blocks/user.tsx new file mode 100644 index 0000000000..6312912c51 --- /dev/null +++ b/twake/frontend/src/app/components/twacode/blocks/user.tsx @@ -0,0 +1,95 @@ +import React, { useEffect, useRef, useState } from 'react'; +import classNames from 'classnames'; +import UserService from 'app/features/users/services/current-user-service'; +import MenusManager from 'app/components/menus/menus-manager.js'; +import UserCard from 'app/components/user-card/user-card'; +import { UserType } from 'app/features/users/types/user'; +import { useUser, useUserByUsername } from 'app/features/users/hooks/use-user'; +import Collections from 'app/deprecated/CollectionsV1/Collections/Collections'; +import { useDirectChannels } from 'app/features/channels/hooks/use-direct-channels'; + +const globalMentions = ['channel', 'everyone', 'all', 'here']; + +type PropsType = { + // User id + id?: string; + // user username + username?: string; + // should we hide the user image? + hideUserImage?: boolean; +}; + +export default (props: PropsType): JSX.Element => { + const { openDiscussion } = useDirectChannels(); + const collection = Collections.get('users'); + const nodeRef = useRef(null); + let user: UserType | undefined; + if (props.id) { + user = useUser(props.id || ''); + } else { + user = useUserByUsername(props.username || ''); + } + + useEffect(() => { + const listener = collection.addListener(useState, [user]); + + return () => { + collection.removeListener(listener); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [user]); + + const displayUserCard = (user: UserType): void => { + if (!nodeRef.current) { + return; + } + + MenusManager.openMenu( + [ + { + type: 'react-element', + reactElement: () => ( + openDiscussion([user.id || ''])} /> + ), + }, + ], + (window as any).getBoundingClientRect(nodeRef.current), + null, + { margin: 8 }, + ); + }; + + const highlighted = + user?.id === UserService.getCurrentUserId() || + globalMentions.includes(props.username || props.id || ''); + + if (user) { + return ( +
displayUserCard(user as UserType)} + style={{ + paddingLeft: props.hideUserImage ? 5 : 0, + backgroundColor: props.hideUserImage ? 'var(--grey-background)' : '', + }} + > + {!props.hideUserImage && ( +
+ )} + {UserService.getFullName(user)} +
+ ); + } else { + return ( + + @{props.username || 'unknown'} + + ); + } +}; diff --git a/twake/frontend/src/app/components/twacode/blocksCompiler.ts b/twake/frontend/src/app/components/twacode/blocksCompiler.ts new file mode 100644 index 0000000000..06722bdabe --- /dev/null +++ b/twake/frontend/src/app/components/twacode/blocksCompiler.ts @@ -0,0 +1,261 @@ +import { + Block, + BlockActions, + BlockContext, + BlockDivider, + BlockElementButton, + BlockElementCheckboxes, + BlockElementDatePicker, + BlockElementImage, + BlockElementMultiselectMenu, + BlockElementOverflowMenus, + BlockElementProgressBar, + BlockElementRadioButtonInput, + BlockElementSelectMenus, + BlockIframe, + BlockImage, + BlockInput, + BlockSection, +} from '../../../../../backend/node/src/services/messages/blocks-types'; + +export const formatData = ( + object: any, + content: any, + flatted: Block[], + level: number | null = null, +) => { + for (let i = 0; i < object.length; i++) { + const recursif = + object[content] && typeof object[content] !== 'string' ? { ...object[content] } : null; + + delete object[content]; + flatted.push(object[i]); + const currentLevel = level ? level + 1 : 1; + if (recursif) { + formatData(recursif, content, flatted, currentLevel); + } + } +}; + +export const blocksToTwacode = (event: Block[]) => { + const blocks: any[] = []; + + event.forEach((obj: Block) => { + let object = obj; + + switch (object.type) { + case 'actions': + object = object as BlockActions; + for (let i = 0; i < object.elements.length; i++) { + const element = object.elements[i]; + createTwacodeElements(element, blocks); + } + lineBreak(blocks); + break; + case 'context': + object = object as BlockContext; + for (let i = 0; i < object.elements.length; i++) { + const element = object.elements[i]; + createTwacodeElements(element, blocks); + } + lineBreak(blocks); + break; + case 'divider': + object = object as BlockDivider; + blocks.push(blocks); + break; + case 'header': + createTwacodeElements({ type: 'mrkdwn', text: `\n **${object.text.text}** \n` }, blocks); + + break; + case 'image': + object = object as BlockImage; + createTwacodeElements(object, blocks, object.type); + lineBreak(blocks); + break; + + case 'input': + object = object as BlockInput; + createTwacodeElements(object, blocks); + break; + case 'section': + object = object as BlockSection; + if (object.text) { + createTwacodeElements(object.text, blocks); + lineBreak(blocks); + } + if (object.fields) { + for (let i = 0; i < object.fields.length; i++) { + const element = object.fields[i]; + createTwacodeElements(element, blocks); + lineBreak(blocks); + } + } + if (object.accessory) { + const element = object.accessory; + createTwacodeElements(element, blocks); + } + lineBreak(blocks); + + break; + case 'iframe': + object = object as BlockIframe; + createTwacodeElements( + { + type: 'iframe', + src: object.iframe_url, + width: object.width, + height: object.height, + }, + blocks, + object.type, + ); + break; + case 'twacode': + blocks.push(object.elements); + break; + default: + // TODO + } + }); + return blocks; +}; + +const createTwacodeElements = (object: any, blocks: any[], type?: any) => { + switch (object.type) { + case 'button': + object = object as BlockElementButton; + blocks.push({ + type: 'button', + content: + object.text.emoji === true + ? { type: 'compile', content: object.text.text } + : object.text.text, + action_id: object.action_id, + value: object.value, + style: object.style ? object.style : 'default', + url: object.url, + }); + break; + case 'checkboxes': + object = object as BlockElementCheckboxes; + blocks.push({ type: 'checkboxes' }); + break; + case 'datepicker': + object = object as BlockElementDatePicker; + blocks.push({ type: 'datepicker' }); + break; + case 'image': + object = object as BlockElementImage; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + object.title + ? blocks.push({ + type: 'system', + content: { + type: 'compile', + content: object.title.text + '\n', + }, + }) + : null; + + blocks.push({ + type: type === 'image' ? 'image' : 'icon', + src: object.image_url, + }); + break; + case 'progress_bar': + object = object as BlockElementProgressBar; + blocks.push({ + type: 'compile', + content: object.title + '\n', + }); + blocks.push({ + type: 'progress_bar', + value: object.value, + }); + break; + case 'multi_static_select': + object = object as BlockElementMultiselectMenu; + blocks.push(generateSelect(object)); + break; + case 'overflow': + object = object as BlockElementOverflowMenus; + blocks.push(generateSelect(object)); + break; + case 'input': + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + object.label.text + ? createTwacodeElements( + { type: 'mrkdwn', text: `**${object.label.text}** \n` }, + blocks, + type, + ) + : null; + createTwacodeElements(object.element, blocks, type); + + break; + case 'plain_text_input': + if (object.readonly === true && object.copiable === true) { + blocks.push({ + type: 'copiable', + content: object.initial_value ? object.initial_value : '', + }); + } else { + blocks.push({ + type: 'input', + placeholder: object.placeholder ? object.placeholder.text : null, + passive_id: object.action_id, + }); + lineBreak(blocks); + } + break; + case 'radio_buttons': + object = object as BlockElementRadioButtonInput; + blocks.push(generateSelect(object)); + break; + case 'static_select': + object = object as BlockElementSelectMenus; + blocks.push(generateSelect(object)); + break; + case 'timepicker': + //not implemented yet + break; + case 'context': + if (object.elements[0].type === 'mrkdwn') { + createTwacodeElements(object.elements[0], blocks); + } else { + createTwacodeElements(object.elements[0], blocks); + } + break; + case 'mrkdwn': + blocks.push({ + type: 'compile', + content: object.text, + }); + break; + case 'plain_text': + blocks.push({ + type: 'text', + content: object.text, + }); + break; + default: + // TODO + } +}; + +const generateSelect = (object: any) => { + return { + type: 'select', + //placeholder not yet implemented + title: '', + values: object.options.map((option: any) => { + return { name: option.text.text, value: option.value }; + }), + action_id: object.action_id, + }; +}; + +const lineBreak = (blocks: any[]) => { + createTwacodeElements({ type: 'mrkdwn', text: '\n' }, blocks); +}; diff --git a/twake/frontend/src/app/components/twacode/compile.tsx b/twake/frontend/src/app/components/twacode/compile.tsx new file mode 100644 index 0000000000..4fac063559 --- /dev/null +++ b/twake/frontend/src/app/components/twacode/compile.tsx @@ -0,0 +1,117 @@ +import _ from 'lodash'; +import React from 'react'; +import PseudoMarkdownCompiler from 'app/features/global/services/pseudo-markdown-compiler-service'; +import { DynamicComponent } from './pseudo-markdown-dictionary'; + +type Props = { + content: any; + isApp: boolean; + eventContainer: any; + textTransform?: any; +}; + +const Compile = (props: Props) => { + let content = props.content; + const isApp = props.isApp; + const eventContainer = props.eventContainer; + let textTransform = props.textTransform; + + if (!content) { + return PseudoMarkdownCompiler.pseudo_markdown['text'].object(''); + } + + if (!textTransform) textTransform = {}; + if (content.formatted || content.prepared) content = content.formatted || content.prepared; + if (typeof content === 'string') content = [content]; + if (content.type || content.start) content = [content]; + + if (!_.isArray(content)) { + content = [content]; + } + + try { + return ( + <> + {content.map((item: any, index: number) => { + if (typeof item === 'string') { + return ( + + {item} + + ); + } else if (Array.isArray(item)) { + return ( + + ); + } else { + let type = PseudoMarkdownCompiler.pseudo_markdown[item.start]; + if (item.type === 'compile' && isApp && typeof item.content === 'string') { + return ( + + ); + } else { + if (item.type) { + type = PseudoMarkdownCompiler.pseudo_markdown_types[item.type]; + } + if (type) { + if (!type.apps_only || isApp) { + //If text transform do it + const old_textTransform = JSON.parse(JSON.stringify(textTransform)); + textTransform = JSON.parse(JSON.stringify(textTransform)); + if (type.textTransform) { + Object.keys(type.textTransform).forEach(key => { + textTransform[key] = type.textTransform[key]; + }); + } + + textTransform = old_textTransform; + + return ( + + + } + data={item} + eventContainer={eventContainer} + textTransform={textTransform} + /> + + ); + } + } + } + } + })} + + ); + } catch (e) { + //Nothing + } + + return ( + + An error occured while showing PseudoMarkdownCompiler message. + + ); +}; + +export default Compile; diff --git a/twake/frontend/src/app/components/twacode/pseudo-markdown-dictionary.tsx b/twake/frontend/src/app/components/twacode/pseudo-markdown-dictionary.tsx new file mode 100644 index 0000000000..d92b617999 --- /dev/null +++ b/twake/frontend/src/app/components/twacode/pseudo-markdown-dictionary.tsx @@ -0,0 +1,382 @@ +import React, { ReactNode } from 'react'; + +import Emojione from 'components/emojione/emojione'; +import HighlightedCode from 'components/highlighted-code/highlighted-code'; +import User from './blocks/user'; +import Chan from './blocks/chan'; +import File from 'components/drive/file'; +import InputWithClipBoard from 'components/input-with-clip-board/input-with-clip-board.js'; +import UserService from 'app/features/users/services/current-user-service'; +import Button from 'components/buttons/button.js'; +import Input from 'components/inputs/input.js'; + +export const DynamicComponent = ({ + type, + child, + data, + eventContainer, + textTransform, +}: { + type?: string; + child?: ReactNode; + data?: any; + eventContainer?: any; + textTransform?: any; +}) => { + if (type === 'text_block_parent') { + return {child}; + } + if (type === 'text') { + return {child}; + } + if (type === 'br') { + return ( + <> +
+ {child} + + ); + } + if (type === 'emoji') { + return ; + } + if (type === 'user') { + const split = (data.content || '').split(':'); + const id = data.id || split[1]; + const username = split[0]; + return ( + <> + + + + ); + } + if (type === 'channel') { + const split = (data.content || '').split(':'); + const id = data.id || split[1]; + const name = split[0]; + return ( + <> + + + + ); + } + if (type === 'underline') return
{child}
; + if (type === 'strikethrough') return
{child}
; + if (type === 'bold') return
{child}
; + if (type === 'italic') return
{child}
; + if (type === 'mquote') return
{child}
; + if (type === 'quote') return
{child}
; + if (type === 'nop') { + return <>{child}; + } + + if (type === 'mcode') { + return ; + } + if (type === 'icode') { + return
{(data.content || '').trim()}
; + } + if (type === 'url') { + if (!data.url && data.url !== undefined) { + return {child}; + } + let url = setUrlProtocol(data.url || data.content); + if (data.user_identifier && UserService.getCurrentUser()) { + let separator = '?'; + if (url.indexOf('?') > 0) { + separator = '&'; + } + url += separator + 'twake_user=' + UserService.getCurrentUser().id; + } + return ( + // eslint-disable-next-line react/jsx-no-target-blank + + {child} + + ); + } + if (type === 'markdown_link') { + const linkData = data.content.split(']('); + const url = linkData[1] || ''; + + return ( + + {linkData[0]} + + ); + } + if (type === 'email') { + return ( + + {child} + + ); + } + if (type === 'system') { + return {child}; + } + + if (type === 'file') { + return ( +
+ +
+ ); + } + if (type === 'iframe') { + return ( +